Ticket #27250: 0002-Apple-keychain-integration-other-changes.patch
File 0002-Apple-keychain-integration-other-changes.patch, 64.0 KB (added by lassi.tuura@…, 13 years ago) |
---|
-
Makefile.in
From 94e42cad73ce6c03abb842a905824586313eabc6 Mon Sep 17 00:00:00 2001 From: Lassi Tuura <lat@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 a/Makefile.in b/Makefile.in index e479a44..65538db 100644
a b SED=@SED@ 56 56 ENT=@ENT@ 57 57 XAUTH_PATH=@XAUTH_PATH@ 58 58 LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ 59 KEYCHAIN_LDFLAGS=@KEYCHAIN_LDFLAGS@ 59 60 EXEEXT=@EXEEXT@ 60 61 MANFMT=@MANFMT@ 61 62 … … SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ 93 94 roaming_common.o roaming_serv.o \ 94 95 sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o 95 96 97 KEYCHAINOBJS=keychain.o 98 96 99 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 97 100 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 98 101 MANTYPE = @MANTYPE@ … … all: $(CONFIGFILES) $(MANPAGES) $(TARGETS) 125 128 $(LIBSSH_OBJS): Makefile.in config.h 126 129 $(SSHOBJS): Makefile.in config.h 127 130 $(SSHDOBJS): Makefile.in config.h 131 $(KEYCHAINOBJS): Makefile.in config.h 128 132 129 133 .c.o: 130 134 $(CC) $(CFLAGS) $(CPPFLAGS) -c $< … … libssh.a: $(LIBSSH_OBJS) 138 142 $(AR) rv $@ $(LIBSSH_OBJS) 139 143 $(RANLIB) $@ 140 144 141 ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) 142 $(LD) -o $@ $(SSHOBJS) $( LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)145 ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) $(KEYCHAINOBJS) 146 $(LD) -o $@ $(SSHOBJS) $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) 143 147 144 148 sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) 145 149 $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) … … sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) 147 151 scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o 148 152 $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 149 153 150 ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o 151 $(LD) -o $@ ssh-add.o $( LDFLAGS) -lssh -lopenbsd-compat $(LIBS)154 ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o $(KEYCHAINOBJS) 155 $(LD) -o $@ ssh-add.o $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 152 156 153 ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o 154 $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $( LDFLAGS) -lssh -lopenbsd-compat $(LIBS)157 ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o $(KEYCHAINOBJS) 158 $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 155 159 156 160 ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o 157 161 $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) … … install-files: 255 259 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) 256 260 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) 257 261 $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) 258 $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)262 $(INSTALL) -m 0711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) 259 263 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) 260 264 $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) 261 265 $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) -
audit-bsm.c
diff --git a/audit-bsm.c b/audit-bsm.c index f196d4f..2899ef5 100644
a b bsm_audit_record(int typ, char *string, au_event_t event_no) 194 194 pid_t pid = getpid(); 195 195 AuditInfoTermID tid = ssh_bsm_tid; 196 196 197 if (the_authctxt != NULL && the_authctxt->valid) { 197 if (the_authctxt == NULL) { 198 error("BSM audit: audit record internal error (NULL ctxt)"); 199 abort(); 200 } 201 202 if (the_authctxt->valid) { 198 203 uid = the_authctxt->pw->pw_uid; 199 204 gid = the_authctxt->pw->pw_gid; 200 205 } -
auth-pam.c
diff --git a/auth-pam.c b/auth-pam.c index 675006e..a195899 100644
a b sshpam_query(void *ctx, char **name, char **info, 793 793 xfree(msg); 794 794 return (0); 795 795 } 796 error("PAM: %s for %s%.100s from %.100s ", msg,796 error("PAM: %s for %s%.100s from %.100s via %s", msg, 797 797 sshpam_authctxt->valid ? "" : "illegal user ", 798 798 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())); 800 801 /* FALLTHROUGH */ 801 802 default: 802 803 *num = 0; -
auth.c
diff --git a/auth.c b/auth.c index cd95da9..94fa21f 100644
a b allowed_user(struct passwd * pw) 209 209 } 210 210 if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { 211 211 /* Get the user's group access list (primary and supplementary) */ 212 if (ga_init(pw ->pw_name, pw->pw_gid) == 0) {212 if (ga_init(pw) == 0) { 213 213 logit("User %.100s from %.100s not allowed because " 214 214 "not in any group", pw->pw_name, hostname); 215 215 return 0; -
authfd.c
diff --git a/authfd.c b/authfd.c index f037e83..c25b157 100644
a b ssh_remove_all_identities(AuthenticationConnection *auth, int version) 689 689 return decode_reply(type); 690 690 } 691 691 692 /* 693 * Adds identities using passphrases stored in the keychain. This call is not 694 * meant to be used by normal applications. 695 */ 696 697 int 698 ssh_add_from_keychain(AuthenticationConnection *auth) 699 { 700 Buffer msg; 701 int type; 702 703 buffer_init(&msg); 704 buffer_put_char(&msg, SSH_AGENTC_ADD_FROM_KEYCHAIN); 705 706 if (ssh_request_reply(auth, &msg, &msg) == 0) { 707 buffer_free(&msg); 708 return 0; 709 } 710 type = buffer_get_char(&msg); 711 buffer_free(&msg); 712 return decode_reply(type); 713 } 714 692 715 int 693 716 decode_reply(int type) 694 717 { -
authfd.h
diff --git a/authfd.h b/authfd.h index 2582a27..7b786fe 100644
a b 49 49 #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 50 50 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 51 51 52 /* keychain */ 53 #define SSH_AGENTC_ADD_FROM_KEYCHAIN 27 54 52 55 #define SSH_AGENT_CONSTRAIN_LIFETIME 1 53 56 #define SSH_AGENT_CONSTRAIN_CONFIRM 2 54 57 -
config.h.in
diff --git a/config.h.in b/config.h.in index baf0011..431720a 100644
a b 71 71 /* Define if your snprintf is busted */ 72 72 #undef BROKEN_SNPRINTF 73 73 74 /* platform uses an in-memory credentials cache */ 75 #undef USE_CCAPI 76 77 /* platform has a Security Authorization Session API */ 78 #undef USE_SECURITY_SESSION_API 79 80 /* Define to 1 if you have the `copyfile' function. */ 81 #undef HAVE_COPYFILE 82 83 /* Define to 1 if you have the <copyfile.h> header file. */ 84 #undef HAVE_COPYFILE_H 85 74 86 /* tcgetattr with ICANON may hang */ 75 87 #undef BROKEN_TCGETATTR_ICANON 76 88 -
configure.ac
diff --git a/configure.ac b/configure.ac index 8cc7ce9..bd8fdaa 100644
a b if test ! -z "$blibpath" ; then 4197 4197 AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile]) 4198 4198 fi 4199 4199 4200 dnl Keychain support 4201 AC_ARG_WITH(keychain, 4202 [ --with-keychain=apple Use Mac OS X Keychain], 4203 [ 4204 case "$withval" in 4205 apple|no) 4206 KEYCHAIN=$withval 4207 ;; 4208 *) 4209 AC_MSG_ERROR(invalid keychain type: $withval) 4210 ;; 4211 esac 4212 ] 4213 ) 4214 if test ! -z "$KEYCHAIN" -a "$KEYCHAIN" != "no"; then 4215 case "$KEYCHAIN" in 4216 apple) 4217 AC_CHECK_HEADERS(Security/Security.h, [ 4218 CPPFLAGS="$CPPFLAGS -D__APPLE_KEYCHAIN__" 4219 KEYCHAIN_LDFLAGS="-framework Security -framework CoreFoundation" 4220 AC_SUBST(KEYCHAIN_LDFLAGS) 4221 ], 4222 AC_MSG_WARN([Security framework not found. Disabling Mac OS X Keychain support.])) 4223 ;; 4224 esac 4225 fi 4226 4200 4227 dnl Adding -Werror to CFLAGS early prevents configure tests from running. 4201 4228 dnl Add now. 4202 4229 CFLAGS="$CFLAGS $werror_flags" 4203 4230 4231 AC_CHECK_FUNCS(copyfile) 4232 AC_CHECK_HEADERS(copyfile.h) 4233 4204 4234 if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then 4205 4235 TEST_SSH_IPV6=no 4206 4236 else -
groupaccess.c
diff --git a/groupaccess.c b/groupaccess.c index 2381aeb..2b5c600 100644
a b 33 33 #include <stdarg.h> 34 34 #include <string.h> 35 35 36 #ifdef __APPLE_MEMBERSHIP__ 37 #include <membership.h> 38 #endif 39 36 40 #include "xmalloc.h" 37 41 #include "groupaccess.h" 38 42 #include "match.h" 39 43 #include "log.h" 40 44 45 #ifdef __APPLE_MEMBERSHIP__ 46 // SPI for 5235093 47 int32_t getgrouplist_2(const char *, gid_t, gid_t **); 48 int32_t getgroupcount(const char *, gid_t); 49 #endif 50 41 51 static int ngroups; 42 52 static char **groups_byname; 53 #ifdef __APPLE_MEMBERSHIP__ 54 uuid_t u_uuid; 55 #endif 43 56 44 57 /* 45 58 * Initialize group access list for user with primary (base) and 46 59 * supplementary groups. Return the number of groups in the list. 47 60 */ 48 61 int 49 ga_init( const char *user, gid_t base)62 ga_init(struct passwd *pw) 50 63 { 51 gid_t *groups_bygid ;64 gid_t *groups_bygid = NULL; 52 65 int i, j; 53 66 struct group *gr; 54 67 68 #ifdef __APPLE_MEMBERSHIP__ 69 if (0 != mbr_uid_to_uuid(pw->pw_uid, u_uuid)) 70 return 0; 71 #endif 72 55 73 if (ngroups > 0) 56 74 ga_free(); 57 75 76 #ifndef __APPLE_MEMBERSHIP__ 58 77 ngroups = NGROUPS_MAX; 59 78 #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX) 60 79 ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX)); 61 #endif 62 80 #endif 63 81 groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid)); 82 #else 83 if (-1 == (ngroups = getgrouplist_2(pw->pw_name, pw->pw_gid, 84 &groups_bygid))) { 85 logit("getgrouplist_2 failed"); 86 return; 87 } 88 #endif 64 89 groups_byname = xcalloc(ngroups, sizeof(*groups_byname)); 65 66 if (getgrouplist(user, base, groups_bygid, &ngroups) == -1) 67 logit("getgrouplist: groups list too small"); 90 #ifndef __APPLE_MEMBERSHIP__ 91 if (getgrouplist(pw->pw_name, pw->pw_gid, groups_bygid, &ngroups) == -1) { 92 logit("getgrouplist: groups list too small"); 93 xfree(groups_bygid); 94 return; 95 } 96 #endif 68 97 for (i = 0, j = 0; i < ngroups; i++) 69 98 if ((gr = getgrgid(groups_bygid[i])) != NULL) 70 99 groups_byname[j++] = xstrdup(gr->gr_name); … … ga_init(const char *user, gid_t base) 75 104 /* 76 105 * Return 1 if one of user's groups is contained in groups. 77 106 * Return 0 otherwise. Use match_pattern() for string comparison. 107 * Use mbr_check_membership() for membership checking on Mac OS X. 78 108 */ 79 109 int 80 110 ga_match(char * const *groups, int n) 81 111 { 112 #ifdef __APPLE_MEMBERSHIP__ 113 int i, ismember = 0; 114 uuid_t g_uuid; 115 struct group *grp; 116 117 for (i = 0; i < n; i++) { 118 if ((grp = getgrnam(groups[i])) == NULL || 119 (mbr_gid_to_uuid(grp->gr_gid, g_uuid) != 0) || 120 (mbr_check_membership(u_uuid, g_uuid, &ismember) != 0)) 121 return 0; 122 if (ismember) 123 return 1; 124 } 125 #else 82 126 int i, j; 83 127 84 128 for (i = 0; i < ngroups; i++) 85 129 for (j = 0; j < n; j++) 86 130 if (match_pattern(groups_byname[i], groups[j])) 87 131 return 1; 132 #endif 88 133 return 0; 89 134 } 90 135 -
groupaccess.h
diff --git a/groupaccess.h b/groupaccess.h index 000578e..ddea117 100644
a b 27 27 #ifndef GROUPACCESS_H 28 28 #define GROUPACCESS_H 29 29 30 int ga_init( const char *, gid_t);30 int ga_init(struct passwd *); 31 31 int ga_match(char * const *, int); 32 32 int ga_match_pattern_list(const char *); 33 33 void ga_free(void); -
new file keychain.c
diff --git a/keychain.c b/keychain.c new file mode 100644 index 0000000..a6d5855
- + 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. */ 49 int kSecPasswordGet = 1<<0; // Get password from keychain or user 50 int kSecPasswordSet = 1<<1; // Set password (passed in if kSecPasswordGet not set, otherwise from user) 51 int kSecPasswordFail = 1<<2; // Wrong password (ignore item in keychain and flag error) 52 OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef); 53 OSStatus SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt32 *length, const void **data); 54 OSStatus SecPasswordSetInitialAccess(SecPasswordRef itemRef, SecAccessRef accessRef); 55 56 #endif 57 58 /* 59 * Platform-specific helper functions. 60 */ 61 62 #if defined(__APPLE_KEYCHAIN__) 63 64 static 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 */ 94 void 95 store_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 209 err: /* 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 xfree(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 */ 251 void 252 remove_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 319 err: /* 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 */ 353 int 354 add_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 419 err: /* Clean up. */ 420 if (itemRef) 421 CFRelease(itemRef); 422 if (cfstr_filename) 423 CFRelease(cfstr_filename); 424 if (filename) 425 xfree(filename); 426 if (passphrase) 427 xfree(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 xfreeing), 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 */ 458 char * 459 keychain_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 xfree(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 641 err: /* 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 xfree(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 } -
new file keychain.h
diff --git a/keychain.h b/keychain.h new file mode 100644 index 0000000..3ab1a6b
- + 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 41 void store_in_keychain(const char *filename, const char *passphrase); 42 void remove_from_keychain(const char *filename); 43 int add_identities_using_keychain( 44 int (*add_identity)(const char *, const char *)); 45 char *keychain_read_passphrase(const char *filename, int oAskPassGUI); -
readconf.c
diff --git a/readconf.c b/readconf.c index 60befde..0fe8fb1 100644
a b typedef enum { 137 137 oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 138 138 oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, 139 139 oKexAlgorithms, oIPQoS, oRequestTTY, 140 #ifdef __APPLE_KEYCHAIN__ 141 oAskPassGUI, 142 #endif 140 143 oDeprecated, oUnsupported 141 144 } OpCodes; 142 145 … … static struct { 257 260 { "kexalgorithms", oKexAlgorithms }, 258 261 { "ipqos", oIPQoS }, 259 262 { "requesttty", oRequestTTY }, 260 263 #ifdef __APPLE_KEYCHAIN__ 264 { "askpassgui", oAskPassGUI }, 265 #endif 261 266 { NULL, oBadOption } 262 267 }; 263 268 … … parse_int: 1074 1079 *intptr = value; 1075 1080 break; 1076 1081 1082 #ifdef __APPLE_KEYCHAIN__ 1083 case oAskPassGUI: 1084 intptr = &options->ask_pass_gui; 1085 goto parse_flag; 1086 #endif 1087 1077 1088 case oDeprecated: 1078 1089 debug("%s line %d: Deprecated option \"%s\"", 1079 1090 filename, linenum, keyword); … … initialize_options(Options * options) 1238 1249 options->ip_qos_interactive = -1; 1239 1250 options->ip_qos_bulk = -1; 1240 1251 options->request_tty = -1; 1252 #ifdef __APPLE_KEYCHAIN__ 1253 options->ask_pass_gui = -1; 1254 #endif 1241 1255 } 1242 1256 1243 1257 /* … … fill_default_options(Options * options) 1408 1422 options->ip_qos_bulk = IPTOS_THROUGHPUT; 1409 1423 if (options->request_tty == -1) 1410 1424 options->request_tty = REQUEST_TTY_AUTO; 1425 #ifdef __APPLE_KEYCHAIN__ 1426 if (options->ask_pass_gui == -1) 1427 options->ask_pass_gui = 1; 1428 #endif 1411 1429 /* options->local_command should not be set by default */ 1412 1430 /* options->proxy_command should not be set by default */ 1413 1431 /* options->user will be set in the main program if appropriate */ -
readconf.h
diff --git a/readconf.h b/readconf.h index 617686f..150e95b 100644
a b typedef struct { 139 139 int use_roaming; 140 140 141 141 int request_tty; 142 143 #ifdef __APPLE_KEYCHAIN__ 144 int ask_pass_gui; 145 #endif 142 146 } Options; 143 147 144 148 #define SSHCTL_MASTER_NO 0 -
scp.1
diff --git a/scp.1 b/scp.1 index 577dd52..c93fb0e 100644
a b 19 19 .Sh SYNOPSIS 20 20 .Nm scp 21 21 .Bk -words 22 .Op Fl 12346BC pqrv22 .Op Fl 12346BCEpqrv 23 23 .Op Fl c Ar cipher 24 24 .Op Fl F Ar ssh_config 25 25 .Op Fl i Ar identity_file … … Passes the 97 97 flag to 98 98 .Xr ssh 1 99 99 to enable compression. 100 .It Fl E 101 Preserves extended attributes, resource forks, and ACLs. Requires both ends to be running Mac OS X 10.4 or later. 100 102 .It Fl c Ar cipher 101 103 Selects the cipher to use for encrypting the data transfer. 102 104 This option is directly passed to -
scp.c
diff --git a/scp.c b/scp.c index 18b2597..439530d 100644
a b 78 78 #ifdef HAVE_SYS_STAT_H 79 79 # include <sys/stat.h> 80 80 #endif 81 #ifdef __APPLE_XSAN__ 82 #include <sys/mount.h> 83 #endif 81 84 #ifdef HAVE_POLL_H 82 85 #include <poll.h> 83 86 #else … … 114 117 #include "misc.h" 115 118 #include "progressmeter.h" 116 119 120 #ifdef HAVE_COPYFILE_H 121 #include <libgen.h> 122 #include <copyfile.h> 123 #endif 124 117 125 extern char *__progname; 118 126 119 127 #define COPY_BUFLEN 16384 … … char *ssh_program = _PATH_SSH_PROGRAM; 150 158 /* This is used to store the pid of ssh_program */ 151 159 pid_t do_cmd_pid = -1; 152 160 161 #ifdef HAVE_COPYFILE 162 int copy_xattr = 0; 163 int md_flag = 0; 164 #endif 165 166 153 167 static void 154 168 killchild(int signo) 155 169 { … … main(int argc, char **argv) 395 409 addargs(&args, "-oClearAllForwardings=yes"); 396 410 397 411 fflag = tflag = 0; 412 #if HAVE_COPYFILE 413 while ((ch = getopt(argc, argv, "dfl:prtvBCEc:i:P:q12346S:o:F:")) != -1) 414 #else 398 415 while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) 416 #endif 399 417 switch (ch) { 400 418 /* User-visible flags. */ 401 419 case '1': … … main(int argc, char **argv) 456 474 showprogress = 0; 457 475 break; 458 476 477 #ifdef HAVE_COPYFILE 478 case 'E': 479 copy_xattr = 1; 480 break; 481 #endif 459 482 /* Server options. */ 460 483 case 'd': 461 484 targetshouldbedirectory = 1; … … main(int argc, char **argv) 505 528 remin = remout = -1; 506 529 do_cmd_pid = -1; 507 530 /* 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 508 535 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", 536 #endif 509 537 verbose_mode ? " -v" : "", 510 538 iamrecursive ? " -r" : "", pflag ? " -p" : "", 511 539 targetshouldbedirectory ? " -d" : ""); … … source(int argc, char **argv) 729 757 int fd = -1, haderr, indx; 730 758 char *last, *name, buf[2048], encname[MAXPATHLEN]; 731 759 int len; 760 #if HAVE_COPYFILE 761 char md_name[MAXPATHLEN]; 762 char *md_tmp; 763 #endif 732 764 733 765 for (indx = 0; indx < argc; ++indx) { 734 766 name = argv[indx]; … … source(int argc, char **argv) 736 768 len = strlen(name); 737 769 while (len > 1 && name[len-1] == '/') 738 770 name[--len] = '\0'; 771 #if HAVE_COPYFILE 772 md_next: 773 statbytes = 0; 774 if (md_flag) { 775 fd = open(md_tmp, O_RDONLY, 0); 776 unlink(md_tmp); 777 free(md_tmp); 778 if (fd < 0) 779 goto syserr; 780 } else { 781 #endif 739 782 if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0) 740 783 goto syserr; 741 784 if (strchr(name, '\n') != NULL) { 742 785 strnvis(encname, name, sizeof(encname), VIS_NL); 743 786 name = encname; 744 787 } 788 #if HAVE_COPYFILE 789 } 790 #endif 745 791 if (fstat(fd, &stb) < 0) { 746 792 syserr: run_err("%s: %s", name, strerror(errno)); 747 793 goto next; … … next: if (fd != -1) { 838 884 else 839 885 run_err("%s: %s", name, strerror(haderr)); 840 886 (void) response(); 887 #ifdef HAVE_COPYFILE 888 if (copy_xattr && md_flag == 0) 889 { 890 if (!copyfile(name, NULL, 0, 891 COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_CHECK)) 892 continue; 893 894 /* 895 * this file will hold the actual metadata 896 * to be transferred 897 */ 898 md_tmp = strdup("/tmp/scp.md.XXXXXX"); 899 md_tmp = mktemp(md_tmp); 900 901 if(copyfile(name, md_tmp, 0, 902 COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_PACK) == 0) 903 { 904 /* 905 * this is the fake name to display 906 */ 907 snprintf(md_name, sizeof md_name, "%s/._%s", dirname(name), basename(name)); 908 name = md_name; 909 md_flag = 1; 910 if (verbose_mode) 911 fprintf(stderr, "copyfile(%s, %s, PACK)\n", name, md_tmp); 912 goto md_next; 913 } 914 } else 915 md_flag = 0; 916 #endif 841 917 } 842 918 } 843 919 … … sink(int argc, char **argv) 932 1008 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) 933 1009 targisdir = 1; 934 1010 for (first = 1;; first = 0) { 1011 #if HAVE_COPYFILE 1012 char md_src[MAXPATHLEN]; 1013 char md_dst[MAXPATHLEN]; 1014 #endif 935 1015 cp = buf; 936 1016 if (atomicio(read, remin, cp, 1) != 1) 937 1017 return; … … sink(int argc, char **argv) 1065 1145 } 1066 1146 omode = mode; 1067 1147 mode |= S_IWRITE; 1148 1149 #if HAVE_COPYFILE 1150 if (copy_xattr && !strncmp(basename(curfile), "._", 2)) 1151 { 1152 int mdfd; 1153 if (targisdir) 1154 { 1155 snprintf(md_src, sizeof md_src, "%s.XXXXXX", np); 1156 snprintf(md_dst, sizeof md_dst, "%s/%s", 1157 dirname(np), basename(np) + 2); 1158 if((mdfd = mkstemp(md_src)) < 0) 1159 continue; 1160 } 1161 else 1162 { 1163 snprintf(md_src, sizeof md_src, "%s/._%s.XXXXXX", 1164 dirname(np), basename(np)); 1165 snprintf(md_dst, sizeof md_dst, "%s", np); 1166 if((mdfd = mkstemp(md_src)) < 0) 1167 continue; 1168 } 1169 if (mdfd >= 0) 1170 close(mdfd); 1171 np = md_src; 1172 } 1173 #endif 1068 1174 if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { 1069 1175 bad: run_err("%s: %s", np, strerror(errno)); 1070 1176 continue; 1071 1177 } 1178 #ifdef __APPLE_XSAN__ 1179 { 1180 /* 1181 * Pre-allocate blocks for the destination file. 1182 */ 1183 fstore_t fst; 1184 1185 fst.fst_flags = 0; 1186 fst.fst_posmode = F_PEOFPOSMODE; 1187 fst.fst_offset = 0; 1188 fst.fst_length = size; 1189 1190 (void) fcntl(ofd, F_PREALLOCATE, &fst); 1191 } 1192 #endif /* __APPLE_XSAN__ */ 1072 1193 (void) atomicio(vwrite, remout, "", 1); 1073 1194 if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) { 1074 1195 (void) close(ofd); … … bad: run_err("%s: %s", np, strerror(errno)); 1153 1274 wrerrno = errno; 1154 1275 } 1155 1276 (void) response(); 1277 #ifdef HAVE_COPYFILE 1278 if (copy_xattr && strncmp(basename(np), "._", 2) == 0) 1279 { 1280 if (verbose_mode) 1281 fprintf(stderr, "copyfile(%s, %s, UNPACK)\n", md_src, md_dst); 1282 if(!copyfile(md_src, md_dst, 0, 1283 COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_UNPACK) < 0) 1284 { 1285 snprintf(md_dst, sizeof md_dst, "%s/._%s", 1286 dirname(md_dst), basename(md_dst)); 1287 rename(md_src, md_dst); 1288 } else 1289 unlink(md_src); 1290 if (setimes && wrerr == NO) { 1291 setimes = 0; 1292 if (utimes(md_dst, tv) < 0) { 1293 run_err("%s: set times: %s", 1294 np, strerror(errno)); 1295 wrerr = DISPLAYED; 1296 } 1297 } 1298 } else 1299 #endif 1156 1300 if (setimes && wrerr == NO) { 1157 1301 setimes = 0; 1158 1302 if (utimes(np, tv) < 0) { … … void 1214 1358 usage(void) 1215 1359 { 1216 1360 (void) fprintf(stderr, 1361 #if HAVE_COPYFILE 1362 "usage: scp [-12346BCEpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" 1363 #else 1217 1364 "usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" 1365 #endif 1218 1366 " [-l limit] [-o ssh_option] [-P port] [-S program]\n" 1219 1367 " [[user@]host1:]file1 ... [[user@]host2:]file2\n"); 1220 1368 exit(1); -
servconf.c
diff --git a/servconf.c b/servconf.c index 756a3a2..0e2678e 100644
a b fill_default_server_options(ServerOptions *options) 148 148 { 149 149 /* Portable-specific options */ 150 150 if (options->use_pam == -1) 151 options->use_pam = 0;151 options->use_pam = 1; 152 152 153 153 /* Standard Options */ 154 154 if (options->protocol == SSH_PROTO_UNKNOWN) … … fill_default_server_options(ServerOptions *options) 237 237 if (options->gss_store_rekey == -1) 238 238 options->gss_store_rekey = 0; 239 239 if (options->password_authentication == -1) 240 options->password_authentication = 1;240 options->password_authentication = 0; 241 241 if (options->kbd_interactive_authentication == -1) 242 242 options->kbd_interactive_authentication = 0; 243 243 if (options->challenge_response_authentication == -1) … … match_cfg_line_group(const char *grps, int line, const char *user) 602 602 if ((pw = getpwnam(user)) == NULL) { 603 603 debug("Can't match group at line %d because user %.100s does " 604 604 "not exist", line, user); 605 } else if (ga_init(pw ->pw_name, pw->pw_gid) == 0) {605 } else if (ga_init(pw) == 0) { 606 606 debug("Can't Match group because user %.100s not in any group " 607 607 "at line %d", user, line); 608 608 } else if (ga_match_pattern_list(grps) != 1) { -
session.c
diff --git a/session.c b/session.c index 6a70400..42e6fac 100644
a b session_pty_req(Session *s) 2063 2063 n_bytes = packet_remaining(); 2064 2064 tty_parse_modes(s->ttyfd, &n_bytes); 2065 2065 2066 #ifndef __APPLE_PRIVPTY__ 2066 2067 if (!use_privsep) 2067 2068 pty_setowner(s->pw, s->tty); 2069 #endif 2068 2070 2069 2071 /* Set window size from the packet. */ 2070 2072 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); … … session_pty_cleanup2(Session *s) 2304 2306 if (s->pid != 0) 2305 2307 record_logout(s->pid, s->tty, s->pw->pw_name); 2306 2308 2309 #ifndef __APPLE_PRIVPTY__ 2307 2310 /* Release the pseudo-tty. */ 2308 2311 if (getuid() == 0) 2309 2312 pty_release(s->tty); 2313 #endif 2310 2314 2311 2315 /* 2312 2316 * Close the server side of the socket pairs. We must do this after -
ssh-add.0
diff --git a/ssh-add.0 b/ssh-add.0 index e1e2a64..74ee18a 100644
a b 1 1 SSH-ADD(1) OpenBSD Reference Manual SSH-ADD(1) 2 2 3 3 NAME 4 ssh-add - adds private key identities to the authentication agent4 ssh-add -- adds private key identities to the authentication agent 5 5 6 6 SYNOPSIS 7 ssh-add [-cDdLlXx ] [-t life] [file ...]7 ssh-add [-cDdLlXxKk] [-t life] [file ...] 8 8 ssh-add -s pkcs11 9 9 ssh-add -e pkcs11 10 10 … … DESCRIPTION 63 63 64 64 -x Lock the agent with a password. 65 65 66 -K When adding identities, each passphrase will also be stored in 67 your keychain. When removing identities with -d, each passphrase 68 will be removed from your keychain. 69 70 -k Add identities to the agent using any passphrases stored in your 71 keychain. 72 66 73 ENVIRONMENT 67 74 DISPLAY and SSH_ASKPASS 68 75 If ssh-add needs a passphrase, it will read the passphrase from -
ssh-add.1
diff --git a/ssh-add.1 b/ssh-add.1 index fd48ff9..0bd1114 100644
a b 43 43 .Nd adds private key identities to the authentication agent 44 44 .Sh SYNOPSIS 45 45 .Nm ssh-add 46 .Op Fl cDdLlXx 46 .Op Fl cDdLlXxKk 47 47 .Op Fl t Ar life 48 48 .Op Ar 49 49 .Nm ssh-add … … specified in 127 127 Unlock the agent. 128 128 .It Fl x 129 129 Lock the agent with a password. 130 .It Fl K 131 When adding identities, each passphrase will also be stored in your 132 keychain. When removing identities with -d, each passphrase will be 133 removed from your keychain. 134 .It Fl k 135 Add identities to the agent using any passphrases stored in your keychain. 130 136 .El 131 137 .Sh ENVIRONMENT 132 138 .Bl -tag -width Ds -
ssh-add.c
diff --git a/ssh-add.c b/ssh-add.c index 6d5e2a9..9621451 100644
a b 62 62 #include "authfile.h" 63 63 #include "pathnames.h" 64 64 #include "misc.h" 65 #include "keychain.h" 65 66 66 67 /* argv0 */ 67 68 extern char *__progname; … … clear_pass(void) 96 97 } 97 98 98 99 static int 99 delete_file(AuthenticationConnection *ac, const char *filename) 100 add_from_keychain(AuthenticationConnection *ac) 101 { 102 if (ssh_add_from_keychain(ac) == 0) 103 return -1; 104 105 fprintf(stderr, "Added keychain identities.\n"); 106 return 0; 107 } 108 109 static int 110 delete_file(AuthenticationConnection *ac, int keychain, const char *filename) 100 111 { 101 112 Key *public; 102 113 char *comment = NULL; 103 114 int ret = -1; 104 115 116 if (keychain) 117 remove_from_keychain(filename); 105 118 public = key_load_public(filename, &comment); 106 119 if (public == NULL) { 107 120 printf("Bad key file %s\n", filename); … … delete_all(AuthenticationConnection *ac) 139 152 } 140 153 141 154 static int 142 add_file(AuthenticationConnection *ac, const char *filename)155 add_file(AuthenticationConnection *ac, int keychain, const char *filename) 143 156 { 144 157 Key *private, *cert; 145 158 char *comment = NULL; … … add_file(AuthenticationConnection *ac, const char *filename) 176 189 177 190 /* At first, try empty passphrase */ 178 191 private = key_parse_private(&keyblob, filename, "", &comment); 192 if (keychain && private != NULL) 193 store_in_keychain(filename, ""); 179 194 if (comment == NULL) 180 195 comment = xstrdup(filename); 181 196 /* try last */ 182 if (private == NULL && pass != NULL) 197 if (private == NULL && pass != NULL) { 183 198 private = key_parse_private(&keyblob, filename, pass, NULL); 199 if (keychain && private != NULL) 200 store_in_keychain(filename, pass); 201 } 184 202 if (private == NULL) { 185 203 /* clear passphrase since it did not work */ 186 204 clear_pass(); … … add_file(AuthenticationConnection *ac, const char *filename) 196 214 } 197 215 private = key_parse_private(&keyblob, filename, pass, 198 216 &comment); 199 if (private != NULL) 217 if (private != NULL) { 218 if (keychain) 219 store_in_keychain(filename, pass); 200 220 break; 221 } 201 222 clear_pass(); 202 223 snprintf(msg, sizeof msg, 203 224 "Bad passphrase, try again for %.200s: ", comment); … … lock_agent(AuthenticationConnection *ac, int lock) 347 368 } 348 369 349 370 static int 350 do_file(AuthenticationConnection *ac, int deleting, char *file)371 do_file(AuthenticationConnection *ac, int deleting, int keychain, char *file) 351 372 { 352 373 if (deleting) { 353 if (delete_file(ac, file) == -1)374 if (delete_file(ac, keychain, file) == -1) 354 375 return -1; 355 376 } else { 356 if (add_file(ac, file) == -1)377 if (add_file(ac, keychain, file) == -1) 357 378 return -1; 358 379 } 359 380 return 0; … … usage(void) 374 395 fprintf(stderr, " -c Require confirmation to sign using identities\n"); 375 396 fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); 376 397 fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); 398 #ifdef KEYCHAIN 399 fprintf(stderr, " -k Add all identities stored in your keychain.\n"); 400 fprintf(stderr, " -K Store passphrases in your keychain.\n"); 401 fprintf(stderr, " With -d, remove passphrases from your keychain.\n"); 402 #endif 377 403 } 378 404 379 405 int … … main(int argc, char **argv) 384 410 AuthenticationConnection *ac = NULL; 385 411 char *pkcs11provider = NULL; 386 412 int i, ch, deleting = 0, ret = 0; 413 int keychain = 0; 387 414 388 415 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 389 416 sanitise_stdfd(); … … main(int argc, char **argv) 400 427 "Could not open a connection to your authentication agent.\n"); 401 428 exit(2); 402 429 } 403 while ((ch = getopt(argc, argv, "lLcdDxXe:s: t:")) != -1) {430 while ((ch = getopt(argc, argv, "lLcdDxXe:s:kKt:")) != -1) { 404 431 switch (ch) { 405 432 case 'l': 406 433 case 'L': … … main(int argc, char **argv) 422 449 if (delete_all(ac) == -1) 423 450 ret = 1; 424 451 goto done; 452 case 'k': 453 if (add_from_keychain(ac) == -1) 454 ret = 1; 455 goto done; 456 case 'K': 457 keychain = 1; 458 break; 425 459 case 's': 426 460 pkcs11provider = optarg; 427 461 break; … … main(int argc, char **argv) 452 486 if (argc == 0) { 453 487 char buf[MAXPATHLEN]; 454 488 struct passwd *pw; 489 char *pw_dir; 455 490 struct stat st; 456 491 int count = 0; 457 492 … … main(int argc, char **argv) 462 497 goto done; 463 498 } 464 499 500 pw_dir = xstrdup(pw->pw_dir); 501 465 502 for (i = 0; default_files[i]; i++) { 466 snprintf(buf, sizeof(buf), "%s/%s", pw ->pw_dir,503 snprintf(buf, sizeof(buf), "%s/%s", pw_dir, 467 504 default_files[i]); 468 505 if (stat(buf, &st) < 0) 469 506 continue; 470 if (do_file(ac, deleting, buf) == -1)507 if (do_file(ac, deleting, keychain, buf) == -1) 471 508 ret = 1; 472 509 else 473 510 count++; 474 511 } 475 512 if (count == 0) 476 513 ret = 1; 514 515 xfree(pw_dir); 477 516 } else { 478 517 for (i = 0; i < argc; i++) { 479 if (do_file(ac, deleting, argv[i]) == -1)518 if (do_file(ac, deleting, keychain, argv[i]) == -1) 480 519 ret = 1; 481 520 } 482 521 } -
ssh-agent.c
diff --git a/ssh-agent.c b/ssh-agent.c index b9498e6..a154096 100644
a b 65 65 #include <time.h> 66 66 #include <string.h> 67 67 #include <unistd.h> 68 #ifdef __APPLE_LAUNCHD__ 69 #include <launch.h> 70 #endif 68 71 69 72 #include "xmalloc.h" 70 73 #include "ssh.h" … … 72 75 #include "buffer.h" 73 76 #include "key.h" 74 77 #include "authfd.h" 78 #include "authfile.h" 75 79 #include "compat.h" 76 80 #include "log.h" 77 81 #include "misc.h" 82 #include "keychain.h" 78 83 79 84 #ifdef ENABLE_PKCS11 80 85 #include "ssh-pkcs11.h" … … process_remove_smartcard_key(SocketEntry *e) 793 798 } 794 799 #endif /* ENABLE_PKCS11 */ 795 800 801 static int 802 add_identity_callback(const char *filename, const char *passphrase) 803 { 804 Key *k; 805 int version; 806 Idtab *tab; 807 808 if ((k = key_load_private(filename, passphrase, NULL)) == NULL) 809 return 1; 810 switch (k->type) { 811 case KEY_RSA: 812 case KEY_RSA1: 813 if (RSA_blinding_on(k->rsa, NULL) != 1) { 814 key_free(k); 815 return 1; 816 } 817 break; 818 } 819 version = k->type == KEY_RSA1 ? 1 : 2; 820 tab = idtab_lookup(version); 821 if (lookup_identity(k, version) == NULL) { 822 Identity *id = xmalloc(sizeof(Identity)); 823 id->key = k; 824 id->comment = xstrdup(filename); 825 if (id->comment == NULL) { 826 key_free(k); 827 return 1; 828 } 829 id->death = 0; 830 id->confirm = 0; 831 TAILQ_INSERT_TAIL(&tab->idlist, id, next); 832 tab->nentries++; 833 } else { 834 key_free(k); 835 return 1; 836 } 837 838 return 0; 839 } 840 841 static void 842 process_add_from_keychain(SocketEntry *e) 843 { 844 int result; 845 846 result = add_identities_using_keychain(&add_identity_callback); 847 848 /* e will be NULL when ssh-agent adds keys on its own at startup */ 849 if (e) { 850 buffer_put_int(&e->output, 1); 851 buffer_put_char(&e->output, 852 result ? SSH_AGENT_FAILURE : SSH_AGENT_SUCCESS); 853 } 854 } 855 796 856 /* dispatch incoming messages */ 797 857 798 858 static void … … process_message(SocketEntry *e) 885 945 process_remove_smartcard_key(e); 886 946 break; 887 947 #endif /* ENABLE_PKCS11 */ 948 case SSH_AGENTC_ADD_FROM_KEYCHAIN: 949 process_add_from_keychain(e); 950 break; 888 951 default: 889 952 /* Unknown message. Respond with failure. */ 890 953 error("Unknown message %d", type); … … usage(void) 1126 1189 int 1127 1190 main(int ac, char **av) 1128 1191 { 1192 #ifdef __APPLE_LAUNCHD__ 1193 int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, l_flag = 0; 1194 #else 1129 1195 int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; 1196 #endif 1130 1197 int sock, fd, ch, result, saved_errno; 1131 1198 u_int nalloc; 1132 1199 char *shell, *format, *pidstr, *agentsocket = NULL; … … main(int ac, char **av) 1160 1227 __progname = ssh_get_progname(av[0]); 1161 1228 seed_rng(); 1162 1229 1230 #ifdef __APPLE_LAUNCHD__ 1231 while ((ch = getopt(ac, av, "cdklsa:t:")) != -1) { 1232 #else 1163 1233 while ((ch = getopt(ac, av, "cdksa:t:")) != -1) { 1234 #endif 1164 1235 switch (ch) { 1165 1236 case 'c': 1166 1237 if (s_flag) … … main(int ac, char **av) 1170 1241 case 'k': 1171 1242 k_flag++; 1172 1243 break; 1244 #ifdef __APPLE_LAUNCHD__ 1245 case 'l': 1246 l_flag++; 1247 break; 1248 #endif 1173 1249 case 's': 1174 1250 if (c_flag) 1175 1251 usage(); … … main(int ac, char **av) 1196 1272 ac -= optind; 1197 1273 av += optind; 1198 1274 1275 #ifdef __APPPLE_LAUNCHD__ 1276 if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || l_flag)) 1277 #else 1199 1278 if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) 1279 #endif 1200 1280 usage(); 1201 1281 1202 1282 if (ac == 0 && !c_flag && !s_flag) { … … main(int ac, char **av) 1252 1332 * Create socket early so it will exist before command gets run from 1253 1333 * the parent. 1254 1334 */ 1335 #ifdef __APPLE_LAUNCHD__ 1336 if (l_flag) { 1337 launch_data_t resp, msg, tmp; 1338 size_t listeners_i; 1339 1340 msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); 1341 1342 resp = launch_msg(msg); 1343 1344 if (NULL == resp) { 1345 perror("launch_msg"); 1346 exit(1); 1347 } 1348 launch_data_free(msg); 1349 switch (launch_data_get_type(resp)) { 1350 case LAUNCH_DATA_ERRNO: 1351 errno = launch_data_get_errno(resp); 1352 perror("launch_msg response"); 1353 exit(1); 1354 case LAUNCH_DATA_DICTIONARY: 1355 break; 1356 default: 1357 fprintf(stderr, "launch_msg unknown response"); 1358 exit(1); 1359 } 1360 tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS); 1361 1362 if (NULL == tmp) { 1363 fprintf(stderr, "no sockets\n"); 1364 exit(1); 1365 } 1366 1367 tmp = launch_data_dict_lookup(tmp, "Listeners"); 1368 1369 if (NULL == tmp) { 1370 fprintf(stderr, "no known listeners\n"); 1371 exit(1); 1372 } 1373 1374 for (listeners_i = 0; listeners_i < launch_data_array_get_count(tmp); listeners_i++) { 1375 launch_data_t obj_at_ind = launch_data_array_get_index(tmp, listeners_i); 1376 new_socket(AUTH_SOCKET, launch_data_get_fd(obj_at_ind)); 1377 } 1378 1379 launch_data_free(resp); 1380 } else { 1381 #endif 1255 1382 sock = socket(AF_UNIX, SOCK_STREAM, 0); 1256 1383 if (sock < 0) { 1257 1384 perror("socket"); … … main(int ac, char **av) 1273 1400 perror("listen"); 1274 1401 cleanup_exit(1); 1275 1402 } 1403 #ifdef __APPLE_LAUNCHD__ 1404 } 1405 #endif 1406 1407 #ifdef __APPLE_LAUNCHD__ 1408 if (l_flag) 1409 goto skip2; 1410 #endif 1276 1411 1277 1412 /* 1278 1413 * Fork, and have the parent execute the command, if any, or present … … skip: 1345 1480 pkcs11_init(0); 1346 1481 #endif 1347 1482 new_socket(AUTH_SOCKET, sock); 1483 skip2: 1348 1484 if (ac > 0) 1349 1485 parent_alive_interval = 10; 1350 1486 idtab_init(); … … skip: 1355 1491 signal(SIGTERM, cleanup_handler); 1356 1492 nalloc = 0; 1357 1493 1494 #ifdef KEYCHAIN 1495 process_add_from_keychain(NULL); 1496 #endif 1497 1358 1498 while (1) { 1359 1499 prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); 1360 1500 result = select(max_fd + 1, readsetp, writesetp, NULL, tvp); -
ssh-keysign.8
diff --git a/ssh-keysign.8 b/ssh-keysign.8 index 5e09e02..612c8f8 100644
a b accessible to others. 71 71 Since they are readable only by root, 72 72 .Nm 73 73 must be set-uid root if host-based authentication is used. 74 Note that 75 .Nm 76 is not set-uid by default on Mac OS X. 74 77 .Pp 75 78 .It Pa /etc/ssh/ssh_host_dsa_key-cert.pub 76 79 .It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub -
sshconnect1.c
diff --git a/sshconnect1.c b/sshconnect1.c index fd07bbf..f9eaeba 100644
a b 47 47 #include "canohost.h" 48 48 #include "hostfile.h" 49 49 #include "auth.h" 50 #include "keychain.h" 50 51 51 52 /* Session id for the current session. */ 52 53 u_char session_id[16]; … … try_rsa_authentication(int idx) 260 261 snprintf(buf, sizeof(buf), 261 262 "Enter passphrase for RSA key '%.100s': ", comment); 262 263 for (i = 0; i < options.number_of_password_prompts; i++) { 264 #ifdef __APPLE_KEYCHAIN__ 265 passphrase = keychain_read_passphrase(comment, options.ask_pass_gui); 266 if (passphrase == NULL) 267 #endif 263 268 passphrase = read_passphrase(buf, 0); 264 269 if (strcmp(passphrase, "") != 0) { 265 270 private = key_load_private_type(KEY_RSA1, -
sshconnect2.c
diff --git a/sshconnect2.c b/sshconnect2.c index 3ddef32..a8ed741 100644
a b 72 72 #include "hostfile.h" 73 73 #include "schnorr.h" 74 74 #include "jpake.h" 75 #include "keychain.h" 75 76 76 77 #ifdef GSSAPI 77 78 #include "ssh-gss.h" … … load_identity_file(char *filename) 1447 1448 snprintf(prompt, sizeof prompt, 1448 1449 "Enter passphrase for key '%.100s': ", filename); 1449 1450 for (i = 0; i < options.number_of_password_prompts; i++) { 1451 #ifdef __APPLE_KEYCHAIN__ 1452 passphrase = keychain_read_passphrase(filename, options.ask_pass_gui); 1453 if (passphrase == NULL) 1454 #endif 1450 1455 passphrase = read_passphrase(prompt, 0); 1451 1456 if (strcmp(passphrase, "") != 0) { 1452 1457 private = key_load_private_type(KEY_UNSPEC, -
sshd.0
diff --git a/sshd.0 b/sshd.0 index e8b4983..471841c 100644
a b FILES 617 617 618 618 SEE ALSO 619 619 scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), 620 ssh-keyscan(1), chroot(2), hosts_access(5), login.conf(5), moduli(5),621 s shd_config(5), inetd(8), sftp-server(8)620 ssh-keyscan(1), chroot(2), hosts_access(5), sshd_config(5) 621 sftp-server(8) 622 622 623 623 AUTHORS 624 624 OpenSSH is a derivative of the original and free ssh 1.2.12 release by -
sshd.8
diff --git a/sshd.8 b/sshd.8 index a91be0f..18941a6 100644
a b The content of this file is not sensitive; it can be world-readable. 950 950 .Xr ssh-keyscan 1 , 951 951 .Xr chroot 2 , 952 952 .Xr hosts_access 5 , 953 .Xr login.conf 5 ,954 .Xr moduli 5 ,955 953 .Xr sshd_config 5 , 956 .Xr inetd 8 ,957 954 .Xr sftp-server 8 958 955 .Sh AUTHORS 959 956 OpenSSH is a derivative of the original and free -
sshd.c
diff --git a/sshd.c b/sshd.c index 112a5f9..4773543 100644
a b main(int ac, char **av) 2076 2076 audit_event(SSH_AUTH_SUCCESS); 2077 2077 #endif 2078 2078 2079 #ifdef USE_PAM 2080 if (options.use_pam) { 2081 do_pam_setcred(1); 2082 do_pam_session(); 2083 } 2084 #endif 2079 2085 #ifdef GSSAPI 2080 2086 if (options.gss_authentication) { 2081 2087 temporarily_use_uid(authctxt->pw); … … main(int ac, char **av) 2083 2089 restore_uid(); 2084 2090 } 2085 2091 #endif 2086 #ifdef USE_PAM2087 if (options.use_pam) {2088 do_pam_setcred(1);2089 do_pam_session();2090 }2091 #endif2092 2092 2093 2093 /* 2094 2094 * In privilege separation, we fork another child and prepare -
sshd_config
diff --git a/sshd_config b/sshd_config index d02d7a7..53966ab 100644
a b 31 31 32 32 # Logging 33 33 # obsoletes QuietMode and FascistLogging 34 #SyslogFacility AUTH 34 SyslogFacility AUTHPRIV 35 35 #LogLevel INFO 36 36 37 37 # Authentication: … … AuthorizedKeysFile .ssh/authorized_keys 59 59 # Don't read the user's ~/.rhosts and ~/.shosts files 60 60 #IgnoreRhosts yes 61 61 62 # To disable tunneled clear text passwords, change to no here! 63 #PasswordAuthentication yes 62 # To disable tunneled clear text passwords, change to no here! Also, 63 # remember to set the UsePAM setting to 'no'. 64 #PasswordAuthentication no 64 65 #PermitEmptyPasswords no 65 66 66 67 # Change to no to disable s/key passwords … … AuthorizedKeysFile .ssh/authorized_keys 87 88 # If you just want the PAM account and session checks to run without 88 89 # PAM authentication, then enable this but set PasswordAuthentication 89 90 # and ChallengeResponseAuthentication to 'no'. 90 #UsePAM no 91 # Also, PAM will deny null passwords by default. If you need to allow 92 # null passwords, add the " nullok" option to the end of the 93 # securityserver.so line in /etc/pam.d/sshd. 94 #UsePAM yes 91 95 92 96 #AllowAgentForwarding yes 93 97 #AllowTcpForwarding yes -
sshd_config.0
diff --git a/sshd_config.0 b/sshd_config.0 index e19ca87..5bee36a 100644
a b DESCRIPTION 436 436 437 437 PasswordAuthentication 438 438 Specifies whether password authentication is allowed. The 439 default is `` yes''.439 default is ``no''. 440 440 441 441 PermitEmptyPasswords 442 442 When password authentication is allowed, it specifies whether the … … DESCRIPTION 619 619 either PasswordAuthentication or ChallengeResponseAuthentication. 620 620 621 621 If UsePAM is enabled, you will not be able to run sshd(8) as a 622 non-root user. The default is `` no''.622 non-root user. The default is ``yes''. 623 623 624 624 UsePrivilegeSeparation 625 625 Specifies whether sshd(8) separates privileges by creating an -
sshd_config.5
diff --git a/sshd_config.5 b/sshd_config.5 index 76c95aa..adebac6 100644
a b are refused if the number of unauthenticated connections reaches 794 794 .It Cm PasswordAuthentication 795 795 Specifies whether password authentication is allowed. 796 796 The default is 797 .Dq yes.797 .Dq no . 798 798 .It Cm PermitEmptyPasswords 799 799 When password authentication is allowed, it specifies whether the 800 800 server allows login to accounts with empty password strings. … … is enabled, you will not be able to run 1089 1089 .Xr sshd 8 1090 1090 as a non-root user. 1091 1091 The default is 1092 .Dq no.1092 .Dq yes . 1093 1093 .It Cm UsePrivilegeSeparation 1094 1094 Specifies whether 1095 1095 .Xr sshd 8