View | Details | Raw Unified | Return to bug 1406
Collapse All | Expand All

(-)../openssh-4.7p1.orig/Makefile.in (-6 / +10 lines)
Lines 56-61 Link Here
56
XAUTH_PATH=@XAUTH_PATH@
56
XAUTH_PATH=@XAUTH_PATH@
57
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
57
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
58
EXEEXT=@EXEEXT@
58
EXEEXT=@EXEEXT@
59
KEYCHAIN_LDFLAGS=@KEYCHAIN_LDFLAGS@
59
60
60
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
61
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
61
INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
62
INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
Lines 88-93 Link Here
88
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
89
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
89
	audit.o audit-bsm.o platform.o
90
	audit.o audit-bsm.o platform.o
90
91
92
KEYCHAINOBJS=keychain.o
93
91
MANPAGES	= 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-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
94
MANPAGES	= 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-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
92
MANPAGES_IN	= scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
95
MANPAGES_IN	= scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
93
MANTYPE		= @MANTYPE@
96
MANTYPE		= @MANTYPE@
Lines 119-124 Link Here
119
$(LIBSSH_OBJS): Makefile.in config.h
122
$(LIBSSH_OBJS): Makefile.in config.h
120
$(SSHOBJS): Makefile.in config.h
123
$(SSHOBJS): Makefile.in config.h
121
$(SSHDOBJS): Makefile.in config.h
124
$(SSHDOBJS): Makefile.in config.h
125
$(KEYCHAINOBJS): Makefile.in config.h
122
126
123
.c.o:
127
.c.o:
124
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
128
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
Lines 132-139 Link Here
132
	$(AR) rv $@ $(LIBSSH_OBJS)
136
	$(AR) rv $@ $(LIBSSH_OBJS)
133
	$(RANLIB) $@
137
	$(RANLIB) $@
134
138
135
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
139
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) $(KEYCHAINOBJS)
136
	$(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
140
	$(LD) -o $@ $(SSHOBJS) $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
137
141
138
sshd$(EXEEXT): libssh.a	$(LIBCOMPAT) $(SSHDOBJS)
142
sshd$(EXEEXT): libssh.a	$(LIBCOMPAT) $(SSHDOBJS)
139
	$(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
143
	$(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
Lines 141-151 Link Here
141
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
145
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
142
	$(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
146
	$(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
143
147
144
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
148
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o $(KEYCHAINOBJS)
145
	$(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
149
	$(LD) -o $@ ssh-add.o $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
146
150
147
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o
151
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o $(KEYCHAINOBJS)
148
	$(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
152
	$(LD) -o $@ ssh-agent.o $(KEYCHAINOBJS) $(LDFLAGS) $(KEYCHAIN_LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
149
153
150
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
154
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
151
	$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
155
	$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
(-)../openssh-4.7p1.orig/authfd.c (+23 lines)
Lines 652-657 Link Here
652
	return decode_reply(type);
652
	return decode_reply(type);
653
}
653
}
654
654
655
/*
656
 * Adds identities using passphrases stored in the keychain.  This call is not
657
 * meant to be used by normal applications.
658
 */
659
660
int
661
ssh_add_from_keychain(AuthenticationConnection *auth)
662
{
663
	Buffer msg;
664
	int type;
665
666
	buffer_init(&msg);
667
	buffer_put_char(&msg, SSH_AGENTC_ADD_FROM_KEYCHAIN);
668
669
	if (ssh_request_reply(auth, &msg, &msg) == 0) {
670
		buffer_free(&msg);
671
		return 0;
672
	}
673
	type = buffer_get_char(&msg);
674
	buffer_free(&msg);
675
	return decode_reply(type);
676
}
677
655
int
678
int
656
decode_reply(int type)
679
decode_reply(int type)
657
{
680
{
(-)../openssh-4.7p1.orig/authfd.h (+3 lines)
Lines 49-54 Link Here
49
#define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
49
#define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
50
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
50
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
51
51
52
/* keychain */
53
#define SSH_AGENTC_ADD_FROM_KEYCHAIN		27
54
52
#define	SSH_AGENT_CONSTRAIN_LIFETIME		1
55
#define	SSH_AGENT_CONSTRAIN_LIFETIME		1
53
#define	SSH_AGENT_CONSTRAIN_CONFIRM		2
56
#define	SSH_AGENT_CONSTRAIN_CONFIRM		2
54
57
(-)../openssh-4.7p1.orig/configure (-2 / +180 lines)
Lines 723-728 Link Here
723
mansubdir
723
mansubdir
724
user_path
724
user_path
725
piddir
725
piddir
726
KEYCHAIN_LDFLAGS
726
LIBOBJS
727
LIBOBJS
727
LTLIBOBJS'
728
LTLIBOBJS'
728
ac_subst_files=''
729
ac_subst_files=''
Lines 1363-1368 Link Here
1363
  --with-bsd-auth         Enable BSD auth support
1364
  --with-bsd-auth         Enable BSD auth support
1364
  --with-pid-dir=PATH     Specify location of ssh.pid file
1365
  --with-pid-dir=PATH     Specify location of ssh.pid file
1365
  --with-lastlog=FILE|DIR specify lastlog location common locations
1366
  --with-lastlog=FILE|DIR specify lastlog location common locations
1367
  --with-keychain=apple   Use Mac OS X Keychain
1366
1368
1367
Some influential environment variables:
1369
Some influential environment variables:
1368
  CC          C compiler command
1370
  CC          C compiler command
Lines 7113-7118 Link Here
7113
#define SSH_TUN_PREPEND_AF 1
7115
#define SSH_TUN_PREPEND_AF 1
7114
_ACEOF
7116
_ACEOF
7115
7117
7118
	KEYCHAIN="apple"
7116
	;;
7119
	;;
7117
*-*-dragonfly*)
7120
*-*-dragonfly*)
7118
	SSHDLIBS="$SSHDLIBS -lcrypt"
7121
	SSHDLIBS="$SSHDLIBS -lcrypt"
Lines 28387-28392 Link Here
28387
echo "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;}
28390
echo "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;}
28388
fi
28391
fi
28389
28392
28393
# Check whether --with-keychain was given.
28394
if test "${with_keychain+set}" = set; then
28395
  withval=$with_keychain;
28396
		case "$withval" in
28397
		apple|no)
28398
			KEYCHAIN=$withval
28399
			;;
28400
		*)
28401
			{ { echo "$as_me:$LINENO: error: invalid keychain type: $withval" >&5
28402
echo "$as_me: error: invalid keychain type: $withval" >&2;}
28403
   { (exit 1); exit 1; }; }
28404
			;;
28405
		esac
28406
28407
28408
fi
28409
28410
if test ! -z "$KEYCHAIN" -a "$KEYCHAIN" != "no"; then
28411
	case "$KEYCHAIN" in
28412
	apple)
28413
28414
for ac_header in Security/Security.h
28415
do
28416
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
28417
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
28418
  { echo "$as_me:$LINENO: checking for $ac_header" >&5
28419
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
28420
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
28421
  echo $ECHO_N "(cached) $ECHO_C" >&6
28422
fi
28423
ac_res=`eval echo '${'$as_ac_Header'}'`
28424
	       { echo "$as_me:$LINENO: result: $ac_res" >&5
28425
echo "${ECHO_T}$ac_res" >&6; }
28426
else
28427
  # Is the header compilable?
28428
{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
28429
echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
28430
cat >conftest.$ac_ext <<_ACEOF
28431
/* confdefs.h.  */
28432
_ACEOF
28433
cat confdefs.h >>conftest.$ac_ext
28434
cat >>conftest.$ac_ext <<_ACEOF
28435
/* end confdefs.h.  */
28436
$ac_includes_default
28437
#include <$ac_header>
28438
_ACEOF
28439
rm -f conftest.$ac_objext
28440
if { (ac_try="$ac_compile"
28441
case "(($ac_try" in
28442
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
28443
  *) ac_try_echo=$ac_try;;
28444
esac
28445
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
28446
  (eval "$ac_compile") 2>conftest.er1
28447
  ac_status=$?
28448
  grep -v '^ *+' conftest.er1 >conftest.err
28449
  rm -f conftest.er1
28450
  cat conftest.err >&5
28451
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
28452
  (exit $ac_status); } && {
28453
	 test -z "$ac_c_werror_flag" ||
28454
	 test ! -s conftest.err
28455
       } && test -s conftest.$ac_objext; then
28456
  ac_header_compiler=yes
28457
else
28458
  echo "$as_me: failed program was:" >&5
28459
sed 's/^/| /' conftest.$ac_ext >&5
28460
28461
	ac_header_compiler=no
28462
fi
28463
28464
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
28465
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
28466
echo "${ECHO_T}$ac_header_compiler" >&6; }
28467
28468
# Is the header present?
28469
{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
28470
echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
28471
cat >conftest.$ac_ext <<_ACEOF
28472
/* confdefs.h.  */
28473
_ACEOF
28474
cat confdefs.h >>conftest.$ac_ext
28475
cat >>conftest.$ac_ext <<_ACEOF
28476
/* end confdefs.h.  */
28477
#include <$ac_header>
28478
_ACEOF
28479
if { (ac_try="$ac_cpp conftest.$ac_ext"
28480
case "(($ac_try" in
28481
  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
28482
  *) ac_try_echo=$ac_try;;
28483
esac
28484
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
28485
  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
28486
  ac_status=$?
28487
  grep -v '^ *+' conftest.er1 >conftest.err
28488
  rm -f conftest.er1
28489
  cat conftest.err >&5
28490
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
28491
  (exit $ac_status); } >/dev/null && {
28492
	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
28493
	 test ! -s conftest.err
28494
       }; then
28495
  ac_header_preproc=yes
28496
else
28497
  echo "$as_me: failed program was:" >&5
28498
sed 's/^/| /' conftest.$ac_ext >&5
28499
28500
  ac_header_preproc=no
28501
fi
28502
28503
rm -f conftest.err conftest.$ac_ext
28504
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
28505
echo "${ECHO_T}$ac_header_preproc" >&6; }
28506
28507
# So?  What about this header?
28508
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
28509
  yes:no: )
28510
    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
28511
echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
28512
    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
28513
echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
28514
    ac_header_preproc=yes
28515
    ;;
28516
  no:yes:* )
28517
    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
28518
echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
28519
    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
28520
echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
28521
    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
28522
echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
28523
    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
28524
echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
28525
    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
28526
echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
28527
    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
28528
echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
28529
    ( cat <<\_ASBOX
28530
## ------------------------------------------- ##
28531
## Report this to openssh-unix-dev@mindrot.org ##
28532
## ------------------------------------------- ##
28533
_ASBOX
28534
     ) | sed "s/^/$as_me: WARNING:     /" >&2
28535
    ;;
28536
esac
28537
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
28538
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
28539
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
28540
  echo $ECHO_N "(cached) $ECHO_C" >&6
28541
else
28542
  eval "$as_ac_Header=\$ac_header_preproc"
28543
fi
28544
ac_res=`eval echo '${'$as_ac_Header'}'`
28545
	       { echo "$as_me:$LINENO: result: $ac_res" >&5
28546
echo "${ECHO_T}$ac_res" >&6; }
28547
28548
fi
28549
if test `eval echo '${'$as_ac_Header'}'` = yes; then
28550
  cat >>confdefs.h <<_ACEOF
28551
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
28552
_ACEOF
28553
28554
				CPPFLAGS="$CPPFLAGS -D__APPLE_KEYCHAIN__"
28555
				KEYCHAIN_LDFLAGS="-framework Security -framework CoreFoundation"
28556
28557
28558
else
28559
  { echo "$as_me:$LINENO: WARNING: Security framework not found. Disabling Mac OS X Keychain support." >&5
28560
echo "$as_me: WARNING: Security framework not found. Disabling Mac OS X Keychain support." >&2;}
28561
fi
28562
28563
done
28564
28565
		;;
28566
	esac
28567
fi
28390
CFLAGS="$CFLAGS $werror_flags"
28568
CFLAGS="$CFLAGS $werror_flags"
28391
28569
28392
28570
Lines 29012-29018 Link Here
29012
_ACEOF
29190
_ACEOF
29013
29191
29014
29192
29015
29016
ac_delim='%!_!# '
29193
ac_delim='%!_!# '
29017
for ac_last_try in false false false false false :; do
29194
for ac_last_try in false false false false false :; do
29018
  cat >conf$$subs.sed <<_ACEOF
29195
  cat >conf$$subs.sed <<_ACEOF
Lines 29164-29174 Link Here
29164
mansubdir!$mansubdir$ac_delim
29341
mansubdir!$mansubdir$ac_delim
29165
user_path!$user_path$ac_delim
29342
user_path!$user_path$ac_delim
29166
piddir!$piddir$ac_delim
29343
piddir!$piddir$ac_delim
29344
KEYCHAIN_LDFLAGS!$KEYCHAIN_LDFLAGS$ac_delim
29167
LIBOBJS!$LIBOBJS$ac_delim
29345
LIBOBJS!$LIBOBJS$ac_delim
29168
LTLIBOBJS!$LTLIBOBJS$ac_delim
29346
LTLIBOBJS!$LTLIBOBJS$ac_delim
29169
_ACEOF
29347
_ACEOF
29170
29348
29171
  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 12; then
29349
  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 13; then
29172
    break
29350
    break
29173
  elif $ac_last_try; then
29351
  elif $ac_last_try; then
29174
    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
29352
    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
(-)../openssh-4.7p1.orig/configure.ac (+28 lines)
Lines 412-417 Link Here
412
	    [Use tunnel device compatibility to OpenBSD])
412
	    [Use tunnel device compatibility to OpenBSD])
413
	AC_DEFINE(SSH_TUN_PREPEND_AF, 1,
413
	AC_DEFINE(SSH_TUN_PREPEND_AF, 1,
414
	    [Prepend the address family to IP tunnel traffic])
414
	    [Prepend the address family to IP tunnel traffic])
415
	KEYCHAIN="apple"
415
	;;
416
	;;
416
*-*-dragonfly*)
417
*-*-dragonfly*)
417
	SSHDLIBS="$SSHDLIBS -lcrypt"
418
	SSHDLIBS="$SSHDLIBS -lcrypt"
Lines 3978-3983 Link Here
3978
	AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile])
3979
	AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile])
3979
fi
3980
fi
3980
3981
3982
dnl Keychain support
3983
AC_ARG_WITH(keychain,
3984
	[  --with-keychain=apple   Use Mac OS X Keychain],
3985
	[
3986
		case "$withval" in
3987
		apple|no)
3988
			KEYCHAIN=$withval
3989
			;;
3990
		*)
3991
			AC_MSG_ERROR(invalid keychain type: $withval)
3992
			;;
3993
		esac
3994
	]
3995
)
3996
if test ! -z "$KEYCHAIN" -a "$KEYCHAIN" != "no"; then
3997
	case "$KEYCHAIN" in
3998
	apple)
3999
		AC_CHECK_HEADERS(Security/Security.h, [
4000
				CPPFLAGS="$CPPFLAGS -D__APPLE_KEYCHAIN__"
4001
				KEYCHAIN_LDFLAGS="-framework Security -framework CoreFoundation"
4002
				AC_SUBST(KEYCHAIN_LDFLAGS)
4003
				],
4004
				AC_MSG_WARN([Security framework not found. Disabling Mac OS X Keychain support.]))
4005
		;;
4006
	esac
4007
fi
4008
3981
dnl Adding -Werror to CFLAGS early prevents configure tests from running.
4009
dnl Adding -Werror to CFLAGS early prevents configure tests from running.
3982
dnl Add now.
4010
dnl Add now.
3983
CFLAGS="$CFLAGS $werror_flags"
4011
CFLAGS="$CFLAGS $werror_flags"
(-)../openssh-4.7p1.orig/keychain.c (+660 lines)
Line 0 Link Here
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
42
#if defined(__APPLE_KEYCHAIN__)
43
44
#include <CoreFoundation/CoreFoundation.h>
45
#include <Security/Security.h>
46
#include <Security/SecPassword.h>
47
48
#endif
49
50
/*
51
 * Platform-specific helper functions.
52
 */
53
54
#if defined(__APPLE_KEYCHAIN__)
55
56
static int get_boolean_preference(const char *key, int default_value,
57
    int foreground)
58
{
59
	int value = default_value;
60
	CFStringRef keyRef = NULL;
61
	CFPropertyListRef valueRef = NULL;
62
63
	keyRef = CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
64
	if (keyRef != NULL)
65
		valueRef = CFPreferencesCopyAppValue(keyRef,
66
		    CFSTR("org.openbsd.openssh"));
67
	if (valueRef != NULL)
68
		if (CFGetTypeID(valueRef) == CFBooleanGetTypeID())
69
			value = CFBooleanGetValue(valueRef);
70
		else if (foreground)
71
			fprintf(stderr, "Ignoring nonboolean %s preference.\n", key);
72
73
	if (keyRef)
74
		CFRelease(keyRef);
75
	if (valueRef)
76
		CFRelease(valueRef);
77
78
	return value;
79
}
80
81
#endif
82
83
/*
84
 * Store the passphrase for a given identity in the keychain.
85
 */
86
void
87
store_in_keychain(const char *filename, const char *passphrase)
88
{
89
90
#if defined(__APPLE_KEYCHAIN__)
91
92
	/*
93
	 * store_in_keychain
94
	 * Mac OS X implementation
95
	 */
96
97
	CFStringRef cfstr_relative_filename = NULL;
98
	CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
99
	CFStringRef cfstr_filename;
100
	CFDataRef cfdata_filename = NULL;
101
	CFIndex filename_len;
102
	UInt8 *label = NULL;
103
	UInt8 *utf8_filename;
104
	OSStatus rv;
105
	SecKeychainItemRef itemRef = NULL;
106
	SecTrustedApplicationRef apps[] = {NULL, NULL, NULL};
107
	CFArrayRef trustedlist = NULL;
108
	SecAccessRef initialAccess = NULL;
109
110
	/* Bail out if KeychainIntegration preference is -bool NO */
111
	if (get_boolean_preference("KeychainIntegration", 1, 1) == 0) {
112
		fprintf(stderr, "Keychain integration is disabled.\n");
113
		goto err;
114
	}
115
116
	/* Interpret filename with the correct encoding. */
117
	if ((cfstr_relative_filename =
118
	    CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
119
	    {
120
		fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
121
		goto err;
122
	}
123
	if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
124
	    cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
125
		fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
126
		goto err;
127
	}
128
	if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
129
	    NULL) {
130
		fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
131
		goto err;
132
	}
133
	if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
134
	    kCFURLPOSIXPathStyle)) == NULL) {
135
		fprintf(stderr, "CFURLGetString failed\n");
136
		goto err;
137
	}
138
	if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
139
	    cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
140
		fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
141
		goto err;
142
	}
143
	filename_len = CFDataGetLength(cfdata_filename);
144
	if ((label = xmalloc(filename_len + 5)) == NULL) {
145
		fprintf(stderr, "xmalloc failed\n");
146
		goto err;
147
	}
148
	memcpy(label, "SSH: ", 5);
149
	utf8_filename = label + 5;
150
	CFDataGetBytes(cfdata_filename, CFRangeMake(0, filename_len),
151
	    utf8_filename);
152
153
	/* Check if we already have this passphrase. */
154
	rv = SecKeychainFindGenericPassword(NULL, 3, "SSH", filename_len,
155
	    (char *)utf8_filename, NULL, NULL, &itemRef);
156
	if (rv == errSecItemNotFound) {
157
		/* Add a new keychain item. */
158
		SecKeychainAttribute attrs[] = {
159
			{kSecLabelItemAttr, filename_len + 5, label},
160
			{kSecServiceItemAttr, 3, "SSH"},
161
			{kSecAccountItemAttr, filename_len, utf8_filename}
162
		};
163
		SecKeychainAttributeList attrList =
164
		    {sizeof(attrs) / sizeof(attrs[0]), attrs};
165
		if (SecTrustedApplicationCreateFromPath("/usr/bin/ssh-agent",
166
		    &apps[0]) != noErr ||
167
		    SecTrustedApplicationCreateFromPath("/usr/bin/ssh-add",
168
		    &apps[1]) != noErr ||
169
		    SecTrustedApplicationCreateFromPath("/usr/bin/ssh",
170
		    &apps[2]) != noErr) {
171
			fprintf(stderr, "SecTrustedApplicationCreateFromPath failed\n");
172
			goto err;
173
		}
174
		if ((trustedlist = CFArrayCreate(NULL, (const void **)apps,
175
		    sizeof(apps) / sizeof(apps[0]), &kCFTypeArrayCallBacks)) ==
176
		    NULL) {
177
			fprintf(stderr, "CFArrayCreate failed\n");
178
			goto err;
179
		}
180
		if (SecAccessCreate(cfstr_filename, trustedlist,
181
		    &initialAccess) != noErr) {
182
			fprintf(stderr, "SecAccessCreate failed\n");
183
			goto err;
184
		}
185
		if (SecKeychainItemCreateFromContent(
186
		    kSecGenericPasswordItemClass, &attrList, strlen(passphrase),
187
		    passphrase, NULL, initialAccess, NULL) == noErr)
188
			fprintf(stderr, "Passphrase stored in keychain: %s\n", filename);
189
		else
190
			fprintf(stderr, "Could not create keychain item\n");
191
	} else if (rv == noErr) {
192
		/* Update an existing keychain item. */
193
		if (SecKeychainItemModifyAttributesAndData(itemRef, NULL,
194
		    strlen(passphrase), passphrase) == noErr)
195
			fprintf(stderr, "Passphrase updated in keychain: %s\n", filename);
196
		else
197
			fprintf(stderr, "Could not modify keychain item\n");
198
	} else
199
		fprintf(stderr, "Could not access keychain\n");
200
201
err:	/* Clean up. */
202
	if (cfstr_relative_filename)
203
		CFRelease(cfstr_relative_filename);
204
	if (cfurl_relative_filename)
205
		CFRelease(cfurl_relative_filename);
206
	if (cfurl_filename)
207
		CFRelease(cfurl_filename);
208
	if (cfdata_filename)
209
		CFRelease(cfdata_filename);
210
	if (label)
211
		xfree(label);
212
	if (itemRef)
213
		CFRelease(itemRef);
214
	if (apps[0])
215
		CFRelease(apps[0]);
216
	if (apps[1])
217
		CFRelease(apps[1]);
218
	if (apps[2])
219
		CFRelease(apps[2]);
220
	if (trustedlist)
221
		CFRelease(trustedlist);
222
	if (initialAccess)
223
		CFRelease(initialAccess);
224
225
#else
226
227
	/*
228
	 * store_in_keychain
229
	 * no keychain implementation
230
	 */
231
232
	fprintf(stderr, "Keychain is not available on this system\n");
233
234
#endif
235
236
}
237
238
/*
239
 * Remove the passphrase for a given identity from the keychain.
240
 */
241
void
242
remove_from_keychain(const char *filename)
243
{
244
245
#if defined(__APPLE_KEYCHAIN__)
246
247
	/*
248
	 * remove_from_keychain
249
	 * Mac OS X implementation
250
	 */
251
252
	CFStringRef cfstr_relative_filename = NULL;
253
	CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
254
	CFStringRef cfstr_filename;
255
	CFDataRef cfdata_filename = NULL;
256
	CFIndex filename_len;
257
	const UInt8 *utf8_filename;
258
	OSStatus rv;
259
	SecKeychainItemRef itemRef = NULL;
260
261
	/* Bail out if KeychainIntegration preference is -bool NO */
262
	if (get_boolean_preference("KeychainIntegration", 1, 1) == 0) {
263
		fprintf(stderr, "Keychain integration is disabled.\n");
264
		goto err;
265
	}
266
267
	/* Interpret filename with the correct encoding. */
268
	if ((cfstr_relative_filename =
269
	    CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
270
	    {
271
		fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
272
		goto err;
273
	}
274
	if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
275
	    cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
276
		fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
277
		goto err;
278
	}
279
	if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
280
	    NULL) {
281
		fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
282
		goto err;
283
	}
284
	if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
285
	    kCFURLPOSIXPathStyle)) == NULL) {
286
		fprintf(stderr, "CFURLGetString failed\n");
287
		goto err;
288
	}
289
	if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
290
	    cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
291
		fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
292
		goto err;
293
	}
294
	filename_len = CFDataGetLength(cfdata_filename);
295
	utf8_filename = CFDataGetBytePtr(cfdata_filename);
296
297
	/* Check if we already have this passphrase. */
298
	rv = SecKeychainFindGenericPassword(NULL, 3, "SSH", filename_len,
299
	    (const char *)utf8_filename, NULL, NULL, &itemRef);
300
	if (rv == noErr) {
301
		/* Remove the passphrase from the keychain. */
302
		if (SecKeychainItemDelete(itemRef) == noErr)
303
			fprintf(stderr, "Passphrase removed from keychain: %s\n", filename);
304
		else
305
			fprintf(stderr, "Could not remove keychain item\n");
306
	} else if (rv != errSecItemNotFound)
307
		fprintf(stderr, "Could not access keychain\n");
308
309
err:	/* Clean up. */
310
	if (cfstr_relative_filename)
311
		CFRelease(cfstr_relative_filename);
312
	if (cfurl_relative_filename)
313
		CFRelease(cfurl_relative_filename);
314
	if (cfurl_filename)
315
		CFRelease(cfurl_filename);
316
	if (cfdata_filename)
317
		CFRelease(cfdata_filename);
318
	if (itemRef)
319
		CFRelease(itemRef);
320
321
#else
322
323
	/*
324
	 * remove_from_keychain
325
	 * no keychain implementation
326
	 */
327
328
	fprintf(stderr, "Keychain is not available on this system\n");
329
330
#endif
331
332
}
333
334
/*
335
 * Add identities to ssh-agent using passphrases stored in the keychain.
336
 * Returns zero on success and nonzero on failure.
337
 * add_identity is a callback into ssh-agent.  It takes a filename and a
338
 * passphrase, and attempts to add the identity to the agent.  It returns
339
 * zero on success and nonzero on failure.
340
 */
341
int
342
add_identities_using_keychain(int (*add_identity)(const char *, const char *))
343
{
344
345
#if defined(__APPLE_KEYCHAIN__)
346
347
	/*
348
	 * add_identities_using_keychain
349
	 * Mac OS X implementation
350
	 */
351
352
	OSStatus rv;
353
	SecKeychainSearchRef searchRef;
354
	SecKeychainItemRef itemRef;
355
	UInt32 length;
356
	void *data;
357
	CFIndex maxsize;
358
359
	/* Bail out if KeychainIntegration preference is -bool NO */
360
	if (get_boolean_preference("KeychainIntegration", 1, 0) == 0)
361
		return 0;
362
363
	/* Search for SSH passphrases in the keychain */
364
	SecKeychainAttribute attrs[] = {
365
		{kSecServiceItemAttr, 3, "SSH"}
366
	};
367
	SecKeychainAttributeList attrList =
368
	    {sizeof(attrs) / sizeof(attrs[0]), attrs};
369
	if ((rv = SecKeychainSearchCreateFromAttributes(NULL,
370
	    kSecGenericPasswordItemClass, &attrList, &searchRef)) != noErr)
371
		return 0;
372
373
	/* Iterate through the search results. */
374
	while ((rv = SecKeychainSearchCopyNext(searchRef, &itemRef)) == noErr) {
375
		UInt32 tag = kSecAccountItemAttr;
376
		UInt32 format = kSecFormatUnknown;
377
		SecKeychainAttributeInfo info = {1, &tag, &format};
378
		SecKeychainAttributeList *itemAttrList = NULL;
379
		CFStringRef cfstr_filename = NULL;
380
		char *filename = NULL;
381
		char *passphrase = NULL;
382
383
		/* Retrieve filename and passphrase. */
384
		if ((rv = SecKeychainItemCopyAttributesAndData(itemRef, &info,
385
		    NULL, &itemAttrList, &length, &data)) != noErr)
386
			goto err;
387
		if (itemAttrList->count != 1)
388
			goto err;
389
		cfstr_filename = CFStringCreateWithBytes(NULL,
390
		    itemAttrList->attr->data, itemAttrList->attr->length,
391
		    kCFStringEncodingUTF8, true);
392
		maxsize = CFStringGetMaximumSizeOfFileSystemRepresentation(
393
		    cfstr_filename);
394
		if ((filename = xmalloc(maxsize)) == NULL)
395
			goto err;
396
		if (CFStringGetFileSystemRepresentation(cfstr_filename,
397
		    filename, maxsize) == false)
398
			goto err;
399
		if ((passphrase = xmalloc(length + 1)) == NULL)
400
			goto err;
401
		memcpy(passphrase, data, length);
402
		passphrase[length] = '\0';
403
404
		/* Add the identity. */
405
		add_identity(filename, passphrase);
406
407
err:		/* Clean up. */
408
		if (itemRef)
409
			CFRelease(itemRef);
410
		if (cfstr_filename)
411
			CFRelease(cfstr_filename);
412
		if (filename)
413
			xfree(filename);
414
		if (passphrase)
415
			xfree(passphrase);
416
		if (itemAttrList)
417
			SecKeychainItemFreeAttributesAndData(itemAttrList,
418
			    data);
419
	}
420
421
	CFRelease(searchRef);
422
423
	return 0;
424
425
#else
426
427
	/*
428
	 * add_identities_using_keychain
429
	 * no implementation
430
	 */
431
432
	return 1;
433
434
#endif
435
436
}
437
438
/*
439
 * Prompt the user for a key's passphrase.  The user will be offered the option
440
 * of storing the passphrase in their keychain.  Returns the passphrase
441
 * (which the caller is responsible for xfreeing), or NULL if this function
442
 * fails or is not implemented.  If this function is not implemented, ssh will
443
 * fall back on the standard read_passphrase function, and the user will need
444
 * to use ssh-add -K to add their keys to the keychain.
445
 */
446
char *
447
keychain_read_passphrase(const char *filename)
448
{
449
450
#if defined(__APPLE_KEYCHAIN__)
451
452
	/*
453
	 * keychain_read_passphrase
454
	 * Mac OS X implementation
455
	 */
456
457
	CFStringRef cfstr_relative_filename = NULL;
458
	CFURLRef cfurl_relative_filename = NULL, cfurl_filename = NULL;
459
	CFStringRef cfstr_filename;
460
	CFDataRef cfdata_filename = NULL;
461
	CFIndex filename_len;
462
	UInt8 *label = NULL;
463
	UInt8 *utf8_filename;
464
	SecPasswordRef passRef = NULL;
465
	SecTrustedApplicationRef apps[] = {NULL, NULL, NULL};
466
	CFArrayRef trustedlist = NULL;
467
	SecAccessRef initialAccess = NULL;
468
	CFURLRef path = NULL;
469
	CFStringRef pathFinal = NULL;
470
	CFURLRef bundle_url = NULL;
471
	CFBundleRef bundle = NULL;
472
	CFStringRef promptTemplate = NULL, prompt = NULL;
473
	UInt32 length;
474
	const void *data;
475
	AuthenticationConnection *ac = NULL;
476
	char *result = NULL;
477
478
	/* Bail out if KeychainIntegration preference is -bool NO */
479
	if (get_boolean_preference("KeychainIntegration", 1, 1) == 0)
480
		goto err;
481
482
	/* Bail out if the user set AskPassGUI preference to -bool NO */
483
	if (get_boolean_preference("AskPassGUI", 1, 1) == 0)
484
		goto err;
485
486
	/* Bail out if we can't communicate with ssh-agent */
487
	if ((ac = ssh_get_authentication_connection()) == NULL)
488
		goto err;
489
490
	/* Interpret filename with the correct encoding. */
491
	if ((cfstr_relative_filename =
492
	    CFStringCreateWithFileSystemRepresentation(NULL, filename)) == NULL)
493
	    {
494
		fprintf(stderr, "CFStringCreateWithFileSystemRepresentation failed\n");
495
		goto err;
496
	}
497
	if ((cfurl_relative_filename = CFURLCreateWithFileSystemPath(NULL,
498
	    cfstr_relative_filename, kCFURLPOSIXPathStyle, false)) == NULL) {
499
		fprintf(stderr, "CFURLCreateWithFileSystemPath failed\n");
500
		goto err;
501
	}
502
	if ((cfurl_filename = CFURLCopyAbsoluteURL(cfurl_relative_filename)) ==
503
	    NULL) {
504
		fprintf(stderr, "CFURLCopyAbsoluteURL failed\n");
505
		goto err;
506
	}
507
	if ((cfstr_filename = CFURLCopyFileSystemPath(cfurl_filename,
508
	    kCFURLPOSIXPathStyle)) == NULL) {
509
		fprintf(stderr, "CFURLGetString failed\n");
510
		goto err;
511
	}
512
	if ((cfdata_filename = CFStringCreateExternalRepresentation(NULL,
513
	    cfstr_filename, kCFStringEncodingUTF8, 0)) == NULL) {
514
		fprintf(stderr, "CFStringCreateExternalRepresentation failed\n");
515
		goto err;
516
	}
517
	filename_len = CFDataGetLength(cfdata_filename);
518
	if ((label = xmalloc(filename_len + 5)) == NULL) {
519
		fprintf(stderr, "xmalloc failed\n");
520
		goto err;
521
	}
522
	memcpy(label, "SSH: ", 5);
523
	utf8_filename = label + 5;
524
	CFDataGetBytes(cfdata_filename, CFRangeMake(0, filename_len),
525
	    utf8_filename);
526
527
	/* Build a SecPasswordRef. */
528
	SecKeychainAttribute searchAttrs[] = {
529
		{kSecServiceItemAttr, 3, "SSH"},
530
		{kSecAccountItemAttr, filename_len, utf8_filename}
531
	};
532
	SecKeychainAttributeList searchAttrList =
533
	    {sizeof(searchAttrs) / sizeof(searchAttrs[0]), searchAttrs};
534
	SecKeychainAttribute attrs[] = {
535
		{kSecLabelItemAttr, filename_len + 5, label},
536
		{kSecServiceItemAttr, 3, "SSH"},
537
		{kSecAccountItemAttr, filename_len, utf8_filename}
538
	};
539
	SecKeychainAttributeList attrList =
540
	    {sizeof(attrs) / sizeof(attrs[0]), attrs};
541
	if (SecGenericPasswordCreate(&searchAttrList, &attrList, &passRef) !=
542
	    noErr) {
543
		fprintf(stderr, "SecGenericPasswordCreate failed\n");
544
		goto err;
545
	}
546
	if (SecTrustedApplicationCreateFromPath("/usr/bin/ssh-agent", &apps[0])
547
	    != noErr ||
548
	    SecTrustedApplicationCreateFromPath("/usr/bin/ssh-add", &apps[1])
549
	    != noErr ||
550
	    SecTrustedApplicationCreateFromPath("/usr/bin/ssh", &apps[2])
551
	    != noErr) {
552
		fprintf(stderr, "SecTrustedApplicationCreateFromPath failed\n");
553
		goto err;
554
	}
555
	if ((trustedlist = CFArrayCreate(NULL, (const void **)apps,
556
	    sizeof(apps) / sizeof(apps[0]), &kCFTypeArrayCallBacks)) == NULL) {
557
		fprintf(stderr, "CFArrayCreate failed\n");
558
		goto err;
559
	}
560
	if (SecAccessCreate(cfstr_filename, trustedlist, &initialAccess)
561
	    != noErr) {
562
		fprintf(stderr, "SecAccessCreate failed\n");
563
		goto err;
564
	}
565
	if (SecPasswordSetInitialAccess(passRef, initialAccess) != noErr) {
566
		fprintf(stderr, "SecPasswordSetInitialAccess failed\n");
567
		goto err;
568
	}
569
570
	/* Request the passphrase from the user. */
571
	path = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8 *)filename,
572
	    strlen(filename), false);
573
	pathFinal = CFURLCopyLastPathComponent(path);
574
	if (!((bundle_url = CFURLCreateWithFileSystemPath(NULL,
575
	    CFSTR("/System/Library/CoreServices/"), kCFURLPOSIXPathStyle, true))
576
	    != NULL && (bundle = CFBundleCreate(NULL, bundle_url)) != NULL &&
577
	    (promptTemplate = CFCopyLocalizedStringFromTableInBundle(
578
	    CFSTR("Enter your password for the SSH key \"%@\"."),
579
	    CFSTR("OpenSSH"), bundle, "Text of the dialog asking the user for"
580
	    "their passphrase.  The %@ will be replaced with the filename of a"
581
	    "specific key.")) != NULL) &&
582
	    (promptTemplate = CFStringCreateCopy(NULL,
583
	    CFSTR("Enter your password for the SSH key \"%@\"."))) == NULL) {
584
		fprintf(stderr, "CFStringCreateCopy failed\n");
585
		goto err;
586
	}
587
	prompt = CFStringCreateWithFormat(NULL, NULL, promptTemplate,
588
	    pathFinal);
589
	switch (SecPasswordAction(passRef, prompt,
590
	    kSecPasswordGet|kSecPasswordFail, &length, &data)) {
591
	case noErr:
592
		result = xmalloc(length + 1);
593
		memcpy(result, data, length);
594
		result[length] = '\0';
595
596
		/* Save password in keychain if requested. */
597
		if (SecPasswordAction(passRef, CFSTR(""), kSecPasswordSet,
598
		    &length, &data) == noErr)
599
			ssh_add_from_keychain(ac);
600
		break;
601
	case errAuthorizationCanceled:
602
		result = xmalloc(1);
603
		*result = '\0';
604
		break;
605
	default:
606
		goto err;
607
	}
608
609
err:	/* Clean up. */
610
	if (cfstr_relative_filename)
611
		CFRelease(cfstr_relative_filename);
612
	if (cfurl_relative_filename)
613
		CFRelease(cfurl_relative_filename);
614
	if (cfurl_filename)
615
		CFRelease(cfurl_filename);
616
	if (cfdata_filename)
617
		CFRelease(cfdata_filename);
618
	if (label)
619
		xfree(label);
620
	if (passRef)
621
		CFRelease(passRef);
622
	if (apps[0])
623
		CFRelease(apps[0]);
624
	if (apps[1])
625
		CFRelease(apps[1]);
626
	if (apps[2])
627
		CFRelease(apps[2]);
628
	if (trustedlist)
629
		CFRelease(trustedlist);
630
	if (initialAccess)
631
		CFRelease(initialAccess);
632
	if (path)
633
		CFRelease(path);
634
	if (pathFinal)
635
		CFRelease(pathFinal);
636
	if (bundle_url)
637
		CFRelease(bundle_url);
638
	if (bundle)
639
		CFRelease(bundle);
640
	if (promptTemplate)
641
		CFRelease(promptTemplate);
642
	if (prompt)
643
		CFRelease(prompt);
644
	if (ac)
645
		ssh_close_authentication_connection(ac);
646
647
	return result;
648
649
#else
650
651
	/*
652
	 * keychain_read_passphrase
653
	 * no implementation
654
	 */
655
656
	return NULL;
657
658
#endif
659
660
}
(-)../openssh-4.7p1.orig/keychain.h (+45 lines)
Line 0 Link Here
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);
(-)../openssh-4.7p1.orig/ssh-add.0 (-1 / +8 lines)
Lines 58-63 Link Here
58
58
59
     -x      Lock the agent with a password.
59
     -x      Lock the agent with a password.
60
60
61
     -K      When adding identities, each passphrase will also be stored in
62
             your keychain.  When removing identities with -d, each passphrase
63
             will be removed from your keychain.
64
65
     -k      Add identities to the agent using any passphrases stored in your
66
             keychain.
67
61
ENVIRONMENT
68
ENVIRONMENT
62
     DISPLAY and SSH_ASKPASS
69
     DISPLAY and SSH_ASKPASS
63
             If ssh-add needs a passphrase, it will read the passphrase from
70
             If ssh-add needs a passphrase, it will read the passphrase from
Lines 103-106 Link Here
103
     ated OpenSSH.  Markus Friedl contributed the support for SSH protocol
110
     ated OpenSSH.  Markus Friedl contributed the support for SSH protocol
104
     versions 1.5 and 2.0.
111
     versions 1.5 and 2.0.
105
112
106
OpenBSD 4.2                      June 12, 2007                               2
113
BSD                           September 25, 1999                           BSD
(-)../openssh-4.7p1.orig/ssh-add.1 (+6 lines)
Lines 121-126 Link Here
121
Unlock the agent.
121
Unlock the agent.
122
.It Fl x
122
.It Fl x
123
Lock the agent with a password.
123
Lock the agent with a password.
124
.It Fl K
125
When adding identities, each passphrase will also be stored in your
126
keychain.  When removing identities with -d, each passphrase will be
127
removed from your keychain.
128
.It Fl k
129
Add identities to the agent using any passphrases stored in your keychain.
124
.El
130
.El
125
.Sh ENVIRONMENT
131
.Sh ENVIRONMENT
126
.Bl -tag -width Ds
132
.Bl -tag -width Ds
(-)../openssh-4.7p1.orig/ssh-add.c (-10 / +44 lines)
Lines 61-66 Link Here
61
#include "authfile.h"
61
#include "authfile.h"
62
#include "pathnames.h"
62
#include "pathnames.h"
63
#include "misc.h"
63
#include "misc.h"
64
#include "keychain.h"
64
65
65
/* argv0 */
66
/* argv0 */
66
extern char *__progname;
67
extern char *__progname;
Lines 92-103 Link Here
92
}
93
}
93
94
94
static int
95
static int
95
delete_file(AuthenticationConnection *ac, const char *filename)
96
add_from_keychain(AuthenticationConnection *ac)
97
{
98
	if (ssh_add_from_keychain(ac) == 0)
99
		return -1;
100
101
	fprintf(stderr, "Added keychain identities.\n");
102
	return 0;
103
}
104
105
static int
106
delete_file(AuthenticationConnection *ac, int keychain, const char *filename)
96
{
107
{
97
	Key *public;
108
	Key *public;
98
	char *comment = NULL;
109
	char *comment = NULL;
99
	int ret = -1;
110
	int ret = -1;
100
111
112
	if (keychain)
113
		remove_from_keychain(filename);
101
	public = key_load_public(filename, &comment);
114
	public = key_load_public(filename, &comment);
102
	if (public == NULL) {
115
	if (public == NULL) {
103
		printf("Bad key file %s\n", filename);
116
		printf("Bad key file %s\n", filename);
Lines 135-141 Link Here
135
}
148
}
136
149
137
static int
150
static int
138
add_file(AuthenticationConnection *ac, const char *filename)
151
add_file(AuthenticationConnection *ac, int keychain, const char *filename)
139
{
152
{
140
	Key *private;
153
	Key *private;
141
	char *comment = NULL;
154
	char *comment = NULL;
Lines 158-168 Link Here
158
171
159
	/* At first, try empty passphrase */
172
	/* At first, try empty passphrase */
160
	private = key_load_private(filename, "", &comment);
173
	private = key_load_private(filename, "", &comment);
174
	if (keychain && private != NULL)
175
		store_in_keychain(filename, "");
161
	if (comment == NULL)
176
	if (comment == NULL)
162
		comment = xstrdup(filename);
177
		comment = xstrdup(filename);
163
	/* try last */
178
	/* try last */
164
	if (private == NULL && pass != NULL)
179
	if (private == NULL && pass != NULL) {
165
		private = key_load_private(filename, pass, NULL);
180
		private = key_load_private(filename, pass, NULL);
181
		if (keychain && private != NULL)
182
			store_in_keychain(filename, pass);
183
	}
166
	if (private == NULL) {
184
	if (private == NULL) {
167
		/* clear passphrase since it did not work */
185
		/* clear passphrase since it did not work */
168
		clear_pass();
186
		clear_pass();
Lines 176-183 Link Here
176
				return -1;
194
				return -1;
177
			}
195
			}
178
			private = key_load_private(filename, pass, &comment);
196
			private = key_load_private(filename, pass, &comment);
179
			if (private != NULL)
197
			if (private != NULL) {
198
				if (keychain)
199
					store_in_keychain(filename, pass);
180
				break;
200
				break;
201
			}
181
			clear_pass();
202
			clear_pass();
182
			snprintf(msg, sizeof msg,
203
			snprintf(msg, sizeof msg,
183
			    "Bad passphrase, try again for %.200s: ", comment);
204
			    "Bad passphrase, try again for %.200s: ", comment);
Lines 294-306 Link Here
294
}
315
}
295
316
296
static int
317
static int
297
do_file(AuthenticationConnection *ac, int deleting, char *file)
318
do_file(AuthenticationConnection *ac, int deleting, int keychain, char *file)
298
{
319
{
299
	if (deleting) {
320
	if (deleting) {
300
		if (delete_file(ac, file) == -1)
321
		if (delete_file(ac, keychain, file) == -1)
301
			return -1;
322
			return -1;
302
	} else {
323
	} else {
303
		if (add_file(ac, file) == -1)
324
		if (add_file(ac, keychain, file) == -1)
304
			return -1;
325
			return -1;
305
	}
326
	}
306
	return 0;
327
	return 0;
Lines 323-328 Link Here
323
	fprintf(stderr, "  -s reader   Add key in smartcard reader.\n");
344
	fprintf(stderr, "  -s reader   Add key in smartcard reader.\n");
324
	fprintf(stderr, "  -e reader   Remove key in smartcard reader.\n");
345
	fprintf(stderr, "  -e reader   Remove key in smartcard reader.\n");
325
#endif
346
#endif
347
#ifdef KEYCHAIN
348
	fprintf(stderr, "  -k          Add all identities stored in your keychain.\n");
349
	fprintf(stderr, "  -K          Store passphrases in your keychain.\n");
350
	fprintf(stderr, "              With -d, remove passphrases from your keychain.\n");
351
#endif
326
}
352
}
327
353
328
int
354
int
Lines 333-338 Link Here
333
	AuthenticationConnection *ac = NULL;
359
	AuthenticationConnection *ac = NULL;
334
	char *sc_reader_id = NULL;
360
	char *sc_reader_id = NULL;
335
	int i, ch, deleting = 0, ret = 0;
361
	int i, ch, deleting = 0, ret = 0;
362
	int keychain = 0;
336
363
337
	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
364
	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
338
	sanitise_stdfd();
365
	sanitise_stdfd();
Lines 350-356 Link Here
350
		    "Could not open a connection to your authentication agent.\n");
377
		    "Could not open a connection to your authentication agent.\n");
351
		exit(2);
378
		exit(2);
352
	}
379
	}
353
	while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
380
	while ((ch = getopt(argc, argv, "lLcdDxXe:s:kKt:")) != -1) {
354
		switch (ch) {
381
		switch (ch) {
355
		case 'l':
382
		case 'l':
356
		case 'L':
383
		case 'L':
Lines 372-377 Link Here
372
			if (delete_all(ac) == -1)
399
			if (delete_all(ac) == -1)
373
				ret = 1;
400
				ret = 1;
374
			goto done;
401
			goto done;
402
		case 'k':
403
			if (add_from_keychain(ac) == -1)
404
				ret = 1;
405
			goto done;
406
		case 'K':
407
			keychain = 1;
408
			break;
375
		case 's':
409
		case 's':
376
			sc_reader_id = optarg;
410
			sc_reader_id = optarg;
377
			break;
411
			break;
Lines 417-423 Link Here
417
			    default_files[i]);
451
			    default_files[i]);
418
			if (stat(buf, &st) < 0)
452
			if (stat(buf, &st) < 0)
419
				continue;
453
				continue;
420
			if (do_file(ac, deleting, buf) == -1)
454
			if (do_file(ac, deleting, keychain, buf) == -1)
421
				ret = 1;
455
				ret = 1;
422
			else
456
			else
423
				count++;
457
				count++;
Lines 426-432 Link Here
426
			ret = 1;
460
			ret = 1;
427
	} else {
461
	} else {
428
		for (i = 0; i < argc; i++) {
462
		for (i = 0; i < argc; i++) {
429
			if (do_file(ac, deleting, argv[i]) == -1)
463
			if (do_file(ac, deleting, keychain, argv[i]) == -1)
430
				ret = 1;
464
				ret = 1;
431
		}
465
		}
432
	}
466
	}
(-)../openssh-4.7p1.orig/ssh-agent.c (+64 lines)
Lines 71-79 Link Here
71
#include "buffer.h"
71
#include "buffer.h"
72
#include "key.h"
72
#include "key.h"
73
#include "authfd.h"
73
#include "authfd.h"
74
#include "authfile.h"
74
#include "compat.h"
75
#include "compat.h"
75
#include "log.h"
76
#include "log.h"
76
#include "misc.h"
77
#include "misc.h"
78
#include "keychain.h"
77
79
78
#ifdef SMARTCARD
80
#ifdef SMARTCARD
79
#include "scard.h"
81
#include "scard.h"
Lines 701-706 Link Here
701
}
703
}
702
#endif /* SMARTCARD */
704
#endif /* SMARTCARD */
703
705
706
static int
707
add_identity_callback(const char *filename, const char *passphrase)
708
{
709
	Key *k;
710
	int version;
711
	Idtab *tab;
712
713
	if ((k = key_load_private(filename, passphrase, NULL)) == NULL)
714
		return 1;
715
	switch (k->type) {
716
	case KEY_RSA:
717
	case KEY_RSA1:
718
		if (RSA_blinding_on(k->rsa, NULL) != 1) {
719
			key_free(k);
720
			return 1;
721
		}
722
		break;
723
	}
724
	version = k->type == KEY_RSA1 ? 1 : 2;
725
	tab = idtab_lookup(version);
726
	if (lookup_identity(k, version) == NULL) {
727
		Identity *id = xmalloc(sizeof(Identity));
728
		id->key = k;
729
		id->comment = xstrdup(filename);
730
		if (id->comment == NULL) {
731
			key_free(k);
732
			return 1;
733
		}
734
		id->death = 0;
735
		id->confirm = 0;
736
		TAILQ_INSERT_TAIL(&tab->idlist, id, next);
737
		tab->nentries++;
738
	} else {
739
		key_free(k);
740
		return 1;
741
	}
742
743
	return 0;
744
}
745
746
static void
747
process_add_from_keychain(SocketEntry *e)
748
{
749
	int result;
750
751
	result = add_identities_using_keychain(&add_identity_callback);
752
753
	/* e will be NULL when ssh-agent adds keys on its own at startup */
754
	if (e) {
755
		buffer_put_int(&e->output, 1);
756
		buffer_put_char(&e->output,
757
		    result ? SSH_AGENT_FAILURE : SSH_AGENT_SUCCESS);
758
	}
759
}
760
704
/* dispatch incoming messages */
761
/* dispatch incoming messages */
705
762
706
static void
763
static void
Lines 793-798 Link Here
793
		process_remove_smartcard_key(e);
850
		process_remove_smartcard_key(e);
794
		break;
851
		break;
795
#endif /* SMARTCARD */
852
#endif /* SMARTCARD */
853
	case SSH_AGENTC_ADD_FROM_KEYCHAIN:
854
		process_add_from_keychain(e);
855
		break;
796
	default:
856
	default:
797
		/* Unknown message.  Respond with failure. */
857
		/* Unknown message.  Respond with failure. */
798
		error("Unknown message %d", type);
858
		error("Unknown message %d", type);
Lines 1256-1261 Link Here
1256
	signal(SIGTERM, cleanup_handler);
1316
	signal(SIGTERM, cleanup_handler);
1257
	nalloc = 0;
1317
	nalloc = 0;
1258
1318
1319
#ifdef KEYCHAIN
1320
	process_add_from_keychain(NULL);
1321
#endif
1322
1259
	while (1) {
1323
	while (1) {
1260
		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
1324
		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
1261
		result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
1325
		result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
(-)../openssh-4.7p1.orig/sshconnect1.c (-1 / +4 lines)
Lines 47-52 Link Here
47
#include "canohost.h"
47
#include "canohost.h"
48
#include "hostfile.h"
48
#include "hostfile.h"
49
#include "auth.h"
49
#include "auth.h"
50
#include "keychain.h"
50
51
51
/* Session id for the current session. */
52
/* Session id for the current session. */
52
u_char session_id[16];
53
u_char session_id[16];
Lines 260-266 Link Here
260
		snprintf(buf, sizeof(buf),
261
		snprintf(buf, sizeof(buf),
261
		    "Enter passphrase for RSA key '%.100s': ", comment);
262
		    "Enter passphrase for RSA key '%.100s': ", comment);
262
		for (i = 0; i < options.number_of_password_prompts; i++) {
263
		for (i = 0; i < options.number_of_password_prompts; i++) {
263
			passphrase = read_passphrase(buf, 0);
264
			passphrase = keychain_read_passphrase(comment);
265
			if (passphrase == NULL)
266
				passphrase = read_passphrase(buf, 0);
264
			if (strcmp(passphrase, "") != 0) {
267
			if (strcmp(passphrase, "") != 0) {
265
				private = key_load_private_type(KEY_RSA1,
268
				private = key_load_private_type(KEY_RSA1,
266
				    authfile, passphrase, NULL, NULL);
269
				    authfile, passphrase, NULL, NULL);
(-)../openssh-4.7p1.orig/sshconnect2.c (-1 / +4 lines)
Lines 64-69 Link Here
64
#include "msg.h"
64
#include "msg.h"
65
#include "pathnames.h"
65
#include "pathnames.h"
66
#include "uidswap.h"
66
#include "uidswap.h"
67
#include "keychain.h"
67
68
68
#ifdef GSSAPI
69
#ifdef GSSAPI
69
#include "ssh-gss.h"
70
#include "ssh-gss.h"
Lines 990-996 Link Here
990
		snprintf(prompt, sizeof prompt,
991
		snprintf(prompt, sizeof prompt,
991
		    "Enter passphrase for key '%.100s': ", filename);
992
		    "Enter passphrase for key '%.100s': ", filename);
992
		for (i = 0; i < options.number_of_password_prompts; i++) {
993
		for (i = 0; i < options.number_of_password_prompts; i++) {
993
			passphrase = read_passphrase(prompt, 0);
994
			passphrase = keychain_read_passphrase(filename);
995
			if (passphrase == NULL)
996
				passphrase = read_passphrase(prompt, 0);
994
			if (strcmp(passphrase, "") != 0) {
997
			if (strcmp(passphrase, "") != 0) {
995
				private = key_load_private_type(KEY_UNSPEC,
998
				private = key_load_private_type(KEY_UNSPEC,
996
				    filename, passphrase, NULL, NULL);
999
				    filename, passphrase, NULL, NULL);

Return to bug 1406