mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-23 14:04:59 +02:00
Source snapshot from Powershell/openssh-portable:latestw_all
This commit is contained in:
parent
d6ce465b15
commit
1ad6c956cc
@ -1,4 +1,4 @@
|
||||
version: 0.0.23.0.{build}
|
||||
version: 0.0.24.0.{build}
|
||||
image: Visual Studio 2015
|
||||
|
||||
branches:
|
||||
|
@ -337,7 +337,7 @@ function Install-OpenSSHTestDependencies
|
||||
if (-not ($isModuleAvailable))
|
||||
{
|
||||
Write-Log -Message "Installing Pester..."
|
||||
choco install Pester -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
|
||||
choco install Pester --version 3.4.6 -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
|
||||
}
|
||||
|
||||
if($Script:PostmortemDebugging -or (($OpenSSHTestInfo -ne $null) -and ($OpenSSHTestInfo["PostmortemDebugging"])))
|
||||
|
@ -264,10 +264,10 @@ if (Get-Service ssh-agent -ErrorAction SilentlyContinue)
|
||||
sc.exe delete ssh-agent 1>$null
|
||||
}
|
||||
|
||||
New-Service -Name ssh-agent -BinaryPathName $sshagentpath -Description "SSH Agent" -StartupType Manual | Out-Null
|
||||
New-Service -Name ssh-agent -BinaryPathName `"$sshagentpath`" -Description "SSH Agent" -StartupType Manual | Out-Null
|
||||
cmd.exe /c 'sc.exe sdset ssh-agent D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RP;;;AU)'
|
||||
|
||||
New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Daemon" -StartupType Manual -DependsOn ssh-agent | Out-Null
|
||||
New-Service -Name sshd -BinaryPathName `"$sshdpath`" -Description "SSH Daemon" -StartupType Manual -DependsOn ssh-agent | Out-Null
|
||||
sc.exe config sshd obj= $sshdAccount
|
||||
sc.exe privs sshd SeAssignPrimaryTokenPrivilege
|
||||
|
||||
|
Binary file not shown.
@ -811,7 +811,7 @@ cleanup:
|
||||
}
|
||||
|
||||
long
|
||||
fileio_lseek(struct w32_io* pio, long offset, int origin)
|
||||
fileio_lseek(struct w32_io* pio, unsigned __int64 offset, int origin)
|
||||
{
|
||||
debug4("lseek - pio:%p", pio);
|
||||
if (origin != SEEK_SET) {
|
||||
@ -820,8 +820,9 @@ fileio_lseek(struct w32_io* pio, long offset, int origin)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pio->read_overlapped.Offset = offset;
|
||||
pio->write_overlapped.Offset = offset;
|
||||
pio->write_overlapped.Offset = pio->read_overlapped.Offset = offset & 0xffffffff;
|
||||
pio->write_overlapped.OffsetHigh = pio->read_overlapped.OffsetHigh = (offset & 0xffffffff00000000) >> 32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ int w32_dup2(int oldfd, int newfd);
|
||||
unsigned int w32_alarm(unsigned int seconds);
|
||||
#define alarm w32_alarm
|
||||
|
||||
long w32_lseek(int fd, long offset, int origin);
|
||||
long w32_lseek(int fd, unsigned __int64 offset, int origin);
|
||||
#define lseek w32_lseek
|
||||
|
||||
#define getdtablesize() MAX_FDS
|
||||
|
@ -43,6 +43,7 @@ LogonUserExExWHelper(wchar_t *user_name, wchar_t *domain, wchar_t *password, DWO
|
||||
PVOID *profile_buffer, LPDWORD profile_length, PQUOTA_LIMITS quota_limits)
|
||||
{
|
||||
wchar_t sspicli_dll_path[MAX_PATH + 1] = { 0, };
|
||||
wchar_t advapi32_dll_path[MAX_PATH + 1] = { 0, };
|
||||
wchar_t system32_path[MAX_PATH + 1] = { 0, };
|
||||
|
||||
if (!GetSystemDirectoryW(system32_path, _countof(system32_path))) {
|
||||
@ -51,14 +52,23 @@ LogonUserExExWHelper(wchar_t *user_name, wchar_t *domain, wchar_t *password, DWO
|
||||
}
|
||||
wcsncpy_s(sspicli_dll_path, _countof(sspicli_dll_path), system32_path, wcsnlen(system32_path, _countof(system32_path)) + 1);
|
||||
wcscat_s(sspicli_dll_path, _countof(sspicli_dll_path), L"\\sspicli.dll");
|
||||
|
||||
if (hMod == NULL)
|
||||
hMod = LoadLibraryW(sspicli_dll_path);
|
||||
wcsncpy_s(advapi32_dll_path, _countof(advapi32_dll_path), system32_path, wcsnlen(system32_path, _countof(system32_path)) + 1);
|
||||
wcscat_s(advapi32_dll_path, _countof(advapi32_dll_path), L"\\advapi32.dll");
|
||||
|
||||
if (hMod == NULL) {
|
||||
hMod = LoadLibraryW(sspicli_dll_path);
|
||||
if (hMod == NULL)
|
||||
debug3("Failed to retrieve the module handle of sspicli.dll with error %d", GetLastError());
|
||||
}
|
||||
|
||||
if (hMod == NULL)
|
||||
hMod = LoadLibraryW(advapi32_dll_path);
|
||||
|
||||
if (hMod == NULL) {
|
||||
debug3("Failed to retrieve the module handle of advapi32.dll with error %d", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (func == NULL)
|
||||
func = (LogonUserExExWType)GetProcAddress(hMod, "LogonUserExExW");
|
||||
|
||||
|
@ -484,7 +484,7 @@ w32_fstat(int fd, struct w32_stat *buf)
|
||||
}
|
||||
|
||||
long
|
||||
w32_lseek(int fd, long offset, int origin)
|
||||
w32_lseek(int fd, unsigned __int64 offset, int origin)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
return fileio_lseek(fd_table.w32_ios[fd], offset, origin);
|
||||
|
@ -163,5 +163,5 @@ int fileio_read(struct w32_io* pio, void *dst, size_t max);
|
||||
int fileio_write(struct w32_io* pio, const void *buf, size_t max);
|
||||
int fileio_fstat(struct w32_io* pio, struct _stat64 *buf);
|
||||
int fileio_stat(const char *path, struct _stat64 *buf);
|
||||
long fileio_lseek(struct w32_io* pio, long offset, int origin);
|
||||
long fileio_lseek(struct w32_io* pio, unsigned __int64 offset, int origin);
|
||||
FILE* fileio_fdopen(struct w32_io* pio, const char *mode);
|
||||
|
@ -124,13 +124,14 @@ int sshd_main(int argc, wchar_t **wargv) {
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t **wargv) {
|
||||
|
||||
if (!StartServiceCtrlDispatcherW(dispatch_table)) {
|
||||
if (GetLastError() != ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
|
||||
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
|
||||
return sshd_main(argc, wargv); /* sshd running NOT as service*/
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sshd_main(argc, wargv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scm_start_service(DWORD num, LPWSTR* args) {
|
||||
|
188
rsa.c
188
rsa.c
@ -1,188 +0,0 @@
|
||||
/* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
*
|
||||
* As far as I am concerned, the code I have written for this software
|
||||
* can be used freely for any purpose. Any derived versions of this
|
||||
* software must be clearly marked as such, and if the derived work is
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1999 Niels Provos. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* Description of the RSA algorithm can be found e.g. from the following
|
||||
* sources:
|
||||
*
|
||||
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
|
||||
*
|
||||
* Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
|
||||
* Computer Security. Prentice-Hall, 1989.
|
||||
*
|
||||
* Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
|
||||
* 1994.
|
||||
*
|
||||
* R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
|
||||
* System and Method. US Patent 4,405,829, 1983.
|
||||
*
|
||||
* Hans Riesel: Prime Numbers and Computer Methods for Factorization.
|
||||
* Birkhauser, 1994.
|
||||
*
|
||||
* The RSA Frequently Asked Questions document by RSA Data Security,
|
||||
* Inc., 1995.
|
||||
*
|
||||
* RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as
|
||||
* included below:
|
||||
*
|
||||
* [gone - had to be deleted - what a pity]
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rsa.h"
|
||||
#include "log.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
int
|
||||
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||
{
|
||||
u_char *inbuf = NULL, *outbuf = NULL;
|
||||
int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
|
||||
olen = BN_num_bytes(key->n);
|
||||
if ((outbuf = malloc(olen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ilen = BN_num_bytes(in);
|
||||
if ((inbuf = malloc(ilen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
BN_bn2bin(in, inbuf);
|
||||
|
||||
if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
|
||||
RSA_PKCS1_PADDING)) <= 0) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (BN_bin2bn(outbuf, len, out) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
r = 0;
|
||||
|
||||
out:
|
||||
if (outbuf != NULL) {
|
||||
explicit_bzero(outbuf, olen);
|
||||
free(outbuf);
|
||||
}
|
||||
if (inbuf != NULL) {
|
||||
explicit_bzero(inbuf, ilen);
|
||||
free(inbuf);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||
{
|
||||
u_char *inbuf = NULL, *outbuf = NULL;
|
||||
int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
olen = BN_num_bytes(key->n);
|
||||
if ((outbuf = malloc(olen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ilen = BN_num_bytes(in);
|
||||
if ((inbuf = malloc(ilen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
BN_bn2bin(in, inbuf);
|
||||
|
||||
if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
|
||||
RSA_PKCS1_PADDING)) <= 0) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
} else if (BN_bin2bn(outbuf, len, out) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
r = 0;
|
||||
out:
|
||||
if (outbuf != NULL) {
|
||||
explicit_bzero(outbuf, olen);
|
||||
free(outbuf);
|
||||
}
|
||||
if (inbuf != NULL) {
|
||||
explicit_bzero(inbuf, ilen);
|
||||
free(inbuf);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* calculate p-1 and q-1 */
|
||||
int
|
||||
rsa_generate_additional_parameters(RSA *rsa)
|
||||
{
|
||||
BIGNUM *aux = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int r;
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((aux = BN_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) ||
|
||||
(BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) ||
|
||||
(BN_sub(aux, rsa->p, BN_value_one()) == 0) ||
|
||||
(BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
r = 0;
|
||||
out:
|
||||
BN_clear_free(aux);
|
||||
BN_CTX_free(ctx);
|
||||
return r;
|
||||
}
|
||||
|
26
rsa.h
26
rsa.h
@ -1,26 +0,0 @@
|
||||
/* $OpenBSD: rsa.h,v 1.17 2014/06/24 01:13:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
* RSA key generation, encryption and decryption.
|
||||
*
|
||||
* As far as I am concerned, the code I have written for this software
|
||||
* can be used freely for any purpose. Any derived versions of this
|
||||
* software must be clearly marked as such, and if the derived work is
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
#ifndef RSA_H
|
||||
#define RSA_H
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *);
|
||||
int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *);
|
||||
int rsa_generate_additional_parameters(RSA *);
|
||||
|
||||
#endif /* RSA_H */
|
91
ssh1.h
91
ssh1.h
@ -1,91 +0,0 @@
|
||||
/* $OpenBSD: ssh1.h,v 1.7 2016/05/04 14:22:33 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
*
|
||||
* As far as I am concerned, the code I have written for this software
|
||||
* can be used freely for any purpose. Any derived versions of this
|
||||
* software must be clearly marked as such, and if the derived work is
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/*
|
||||
* Definition of message types. New values can be added, but old values
|
||||
* should not be removed or without careful consideration of the consequences
|
||||
* for compatibility. The maximum value is 254; value 255 is reserved for
|
||||
* future extension.
|
||||
*/
|
||||
/* Ranges */
|
||||
#define SSH_MSG_MIN 1
|
||||
#define SSH_MSG_MAX 254
|
||||
/* Message name */ /* msg code */ /* arguments */
|
||||
#define SSH_MSG_DISCONNECT 1 /* cause (string) */
|
||||
#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
|
||||
#define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
|
||||
#define SSH_CMSG_USER 4 /* user (string) */
|
||||
#define SSH_CMSG_AUTH_RHOSTS 5 /* user (string) */
|
||||
#define SSH_CMSG_AUTH_RSA 6 /* modulus (BIGNUM) */
|
||||
#define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (BIGNUM) */
|
||||
#define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (BIGNUM) */
|
||||
#define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */
|
||||
#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */
|
||||
#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */
|
||||
#define SSH_CMSG_EXEC_SHELL 12 /* */
|
||||
#define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */
|
||||
#define SSH_SMSG_SUCCESS 14 /* */
|
||||
#define SSH_SMSG_FAILURE 15 /* */
|
||||
#define SSH_CMSG_STDIN_DATA 16 /* data (string) */
|
||||
#define SSH_SMSG_STDOUT_DATA 17 /* data (string) */
|
||||
#define SSH_SMSG_STDERR_DATA 18 /* data (string) */
|
||||
#define SSH_CMSG_EOF 19 /* */
|
||||
#define SSH_SMSG_EXITSTATUS 20 /* status (int) */
|
||||
#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* channel (int) */
|
||||
#define SSH_MSG_CHANNEL_OPEN_FAILURE 22 /* channel (int) */
|
||||
#define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */
|
||||
#define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */
|
||||
#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */
|
||||
/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */
|
||||
#define SSH_SMSG_X11_OPEN 27 /* channel (int) */
|
||||
#define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */
|
||||
#define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */
|
||||
#define SSH_CMSG_AGENT_REQUEST_FORWARDING 30 /* */
|
||||
#define SSH_SMSG_AGENT_OPEN 31 /* port (int) */
|
||||
#define SSH_MSG_IGNORE 32 /* string */
|
||||
#define SSH_CMSG_EXIT_CONFIRMATION 33 /* */
|
||||
#define SSH_CMSG_X11_REQUEST_FORWARDING 34 /* proto,data (s,s) */
|
||||
#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */
|
||||
#define SSH_MSG_DEBUG 36 /* string */
|
||||
#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */
|
||||
#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k (int) */
|
||||
#define SSH_CMSG_AUTH_TIS 39 /* we use this for s/key */
|
||||
#define SSH_SMSG_AUTH_TIS_CHALLENGE 40 /* challenge (string) */
|
||||
#define SSH_CMSG_AUTH_TIS_RESPONSE 41 /* response (string) */
|
||||
#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
|
||||
#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
|
||||
#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */
|
||||
#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */
|
||||
|
||||
/* protocol version 1.5 overloads some version 1.3 message types */
|
||||
#define SSH_MSG_CHANNEL_INPUT_EOF SSH_MSG_CHANNEL_CLOSE
|
||||
#define SSH_MSG_CHANNEL_OUTPUT_CLOSE SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
|
||||
|
||||
/*
|
||||
* Authentication methods. New types can be added, but old types should not
|
||||
* be removed for compatibility. The maximum allowed value is 31.
|
||||
*/
|
||||
#define SSH_AUTH_RHOSTS 1
|
||||
#define SSH_AUTH_RSA 2
|
||||
#define SSH_AUTH_PASSWORD 3
|
||||
#define SSH_AUTH_RHOSTS_RSA 4
|
||||
#define SSH_AUTH_TIS 5
|
||||
#define SSH_AUTH_KERBEROS 6
|
||||
#define SSH_PASS_KERBEROS_TGT 7
|
||||
/* 8 to 15 are reserved */
|
||||
#define SSH_PASS_AFS_TOKEN 21
|
||||
|
||||
/* Protocol flags. These are bit masks. */
|
||||
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
|
||||
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
|
774
sshconnect1.c
774
sshconnect1.c
@ -1,774 +0,0 @@
|
||||
/* $OpenBSD: sshconnect1.c,v 1.80 2017/03/10 03:53:11 dtucker Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
* Code to connect to a remote host, and to perform the client side of the
|
||||
* login (authentication) dialog.
|
||||
*
|
||||
* As far as I am concerned, the code I have written for this software
|
||||
* can be used freely for any purpose. Any derived versions of this
|
||||
* software must be clearly marked as such, and if the derived work is
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "ssh1.h"
|
||||
#include "rsa.h"
|
||||
#include "buffer.h"
|
||||
#include "packet.h"
|
||||
#include "key.h"
|
||||
#include "cipher.h"
|
||||
#include "kex.h"
|
||||
#include "uidswap.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "readconf.h"
|
||||
#include "authfd.h"
|
||||
#include "sshconnect.h"
|
||||
#include "authfile.h"
|
||||
#include "canohost.h"
|
||||
#include "hostfile.h"
|
||||
#include "auth.h"
|
||||
#include "digest.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
/* Session id for the current session. */
|
||||
u_char session_id[16];
|
||||
u_int supported_authentications = 0;
|
||||
|
||||
extern Options options;
|
||||
extern char *__progname;
|
||||
|
||||
/*
|
||||
* Checks if the user has an authentication agent, and if so, tries to
|
||||
* authenticate using the agent.
|
||||
*/
|
||||
static int
|
||||
try_agent_authentication(void)
|
||||
{
|
||||
int r, type, agent_fd, ret = 0;
|
||||
u_char response[16];
|
||||
size_t i;
|
||||
BIGNUM *challenge;
|
||||
struct ssh_identitylist *idlist = NULL;
|
||||
|
||||
/* Get connection to the agent. */
|
||||
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
|
||||
if (r != SSH_ERR_AGENT_NOT_PRESENT)
|
||||
debug("%s: ssh_get_authentication_socket: %s",
|
||||
__func__, ssh_err(r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((challenge = BN_new()) == NULL)
|
||||
fatal("try_agent_authentication: BN_new failed");
|
||||
|
||||
/* Loop through identities served by the agent. */
|
||||
if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) {
|
||||
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
|
||||
debug("%s: ssh_fetch_identitylist: %s",
|
||||
__func__, ssh_err(r));
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < idlist->nkeys; i++) {
|
||||
/* Try this identity. */
|
||||
debug("Trying RSA authentication via agent with '%.100s'",
|
||||
idlist->comments[i]);
|
||||
|
||||
/* Tell the server that we are willing to authenticate using this key. */
|
||||
packet_start(SSH_CMSG_AUTH_RSA);
|
||||
packet_put_bignum(idlist->keys[i]->rsa->n);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
/* Wait for server's response. */
|
||||
type = packet_read();
|
||||
|
||||
/* The server sends failure if it doesn't like our key or
|
||||
does not support RSA authentication. */
|
||||
if (type == SSH_SMSG_FAILURE) {
|
||||
debug("Server refused our key.");
|
||||
continue;
|
||||
}
|
||||
/* Otherwise it should have sent a challenge. */
|
||||
if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
|
||||
packet_disconnect("Protocol error during RSA authentication: %d",
|
||||
type);
|
||||
|
||||
packet_get_bignum(challenge);
|
||||
packet_check_eom();
|
||||
|
||||
debug("Received RSA challenge from server.");
|
||||
|
||||
/* Ask the agent to decrypt the challenge. */
|
||||
if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i],
|
||||
challenge, session_id, response)) != 0) {
|
||||
/*
|
||||
* The agent failed to authenticate this identifier
|
||||
* although it advertised it supports this. Just
|
||||
* return a wrong value.
|
||||
*/
|
||||
logit("Authentication agent failed to decrypt "
|
||||
"challenge: %s", ssh_err(r));
|
||||
explicit_bzero(response, sizeof(response));
|
||||
}
|
||||
debug("Sending response to RSA challenge.");
|
||||
|
||||
/* Send the decrypted challenge back to the server. */
|
||||
packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
|
||||
for (i = 0; i < 16; i++)
|
||||
packet_put_char(response[i]);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
/* Wait for response from the server. */
|
||||
type = packet_read();
|
||||
|
||||
/*
|
||||
* The server returns success if it accepted the
|
||||
* authentication.
|
||||
*/
|
||||
if (type == SSH_SMSG_SUCCESS) {
|
||||
debug("RSA authentication accepted by server.");
|
||||
ret = 1;
|
||||
break;
|
||||
} else if (type != SSH_SMSG_FAILURE)
|
||||
packet_disconnect("Protocol error waiting RSA auth "
|
||||
"response: %d", type);
|
||||
}
|
||||
if (ret != 1)
|
||||
debug("RSA authentication using agent refused.");
|
||||
out:
|
||||
ssh_free_identitylist(idlist);
|
||||
ssh_close_authentication_socket(agent_fd);
|
||||
BN_clear_free(challenge);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes the proper response to a RSA challenge, and sends the response to
|
||||
* the server.
|
||||
*/
|
||||
static void
|
||||
respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
|
||||
{
|
||||
u_char buf[32], response[16];
|
||||
struct ssh_digest_ctx *md;
|
||||
int i, len;
|
||||
|
||||
/* Decrypt the challenge using the private key. */
|
||||
/* XXX think about Bleichenbacher, too */
|
||||
if (rsa_private_decrypt(challenge, challenge, prv) != 0)
|
||||
packet_disconnect(
|
||||
"respond_to_rsa_challenge: rsa_private_decrypt failed");
|
||||
|
||||
/* Compute the response. */
|
||||
/* The response is MD5 of decrypted challenge plus session id. */
|
||||
len = BN_num_bytes(challenge);
|
||||
if (len <= 0 || (u_int)len > sizeof(buf))
|
||||
packet_disconnect(
|
||||
"respond_to_rsa_challenge: bad challenge length %d", len);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
BN_bn2bin(challenge, buf + sizeof(buf) - len);
|
||||
if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
|
||||
ssh_digest_update(md, buf, 32) < 0 ||
|
||||
ssh_digest_update(md, session_id, 16) < 0 ||
|
||||
ssh_digest_final(md, response, sizeof(response)) < 0)
|
||||
fatal("%s: md5 failed", __func__);
|
||||
ssh_digest_free(md);
|
||||
|
||||
debug("Sending response to host key RSA challenge.");
|
||||
|
||||
/* Send the response back to the server. */
|
||||
packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
|
||||
for (i = 0; i < 16; i++)
|
||||
packet_put_char(response[i]);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
explicit_bzero(buf, sizeof(buf));
|
||||
explicit_bzero(response, sizeof(response));
|
||||
explicit_bzero(&md, sizeof(md));
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the user has authentication file, and if so, tries to authenticate
|
||||
* the user using it.
|
||||
*/
|
||||
static int
|
||||
try_rsa_authentication(int idx)
|
||||
{
|
||||
BIGNUM *challenge;
|
||||
Key *public, *private;
|
||||
char buf[300], *passphrase = NULL, *comment, *authfile;
|
||||
int i, perm_ok = 1, type, quit;
|
||||
|
||||
public = options.identity_keys[idx];
|
||||
authfile = options.identity_files[idx];
|
||||
comment = xstrdup(authfile);
|
||||
|
||||
debug("Trying RSA authentication with key '%.100s'", comment);
|
||||
|
||||
/* Tell the server that we are willing to authenticate using this key. */
|
||||
packet_start(SSH_CMSG_AUTH_RSA);
|
||||
packet_put_bignum(public->rsa->n);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
/* Wait for server's response. */
|
||||
type = packet_read();
|
||||
|
||||
/*
|
||||
* The server responds with failure if it doesn't like our key or
|
||||
* doesn't support RSA authentication.
|
||||
*/
|
||||
if (type == SSH_SMSG_FAILURE) {
|
||||
debug("Server refused our key.");
|
||||
free(comment);
|
||||
return 0;
|
||||
}
|
||||
/* Otherwise, the server should respond with a challenge. */
|
||||
if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
|
||||
packet_disconnect("Protocol error during RSA authentication: %d", type);
|
||||
|
||||
/* Get the challenge from the packet. */
|
||||
if ((challenge = BN_new()) == NULL)
|
||||
fatal("try_rsa_authentication: BN_new failed");
|
||||
packet_get_bignum(challenge);
|
||||
packet_check_eom();
|
||||
|
||||
debug("Received RSA challenge from server.");
|
||||
|
||||
/*
|
||||
* If the key is not stored in external hardware, we have to
|
||||
* load the private key. Try first with empty passphrase; if it
|
||||
* fails, ask for a passphrase.
|
||||
*/
|
||||
if (public->flags & SSHKEY_FLAG_EXT)
|
||||
private = public;
|
||||
else
|
||||
private = key_load_private_type(KEY_RSA1, authfile, "", NULL,
|
||||
&perm_ok);
|
||||
if (private == NULL && !options.batch_mode && perm_ok) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"Enter passphrase for RSA key '%.100s': ", comment);
|
||||
for (i = 0; i < options.number_of_password_prompts; i++) {
|
||||
passphrase = read_passphrase(buf, 0);
|
||||
if (strcmp(passphrase, "") != 0) {
|
||||
private = key_load_private_type(KEY_RSA1,
|
||||
authfile, passphrase, NULL, NULL);
|
||||
quit = 0;
|
||||
} else {
|
||||
debug2("no passphrase given, try next key");
|
||||
quit = 1;
|
||||
}
|
||||
if (private != NULL || quit)
|
||||
break;
|
||||
debug2("bad passphrase given, try again...");
|
||||
}
|
||||
}
|
||||
|
||||
if (private != NULL)
|
||||
maybe_add_key_to_agent(authfile, private, comment, passphrase);
|
||||
|
||||
if (passphrase != NULL) {
|
||||
explicit_bzero(passphrase, strlen(passphrase));
|
||||
free(passphrase);
|
||||
}
|
||||
|
||||
/* We no longer need the comment. */
|
||||
free(comment);
|
||||
|
||||
if (private == NULL) {
|
||||
if (!options.batch_mode && perm_ok)
|
||||
error("Bad passphrase.");
|
||||
|
||||
/* Send a dummy response packet to avoid protocol error. */
|
||||
packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
|
||||
for (i = 0; i < 16; i++)
|
||||
packet_put_char(0);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
/* Expect the server to reject it... */
|
||||
packet_read_expect(SSH_SMSG_FAILURE);
|
||||
BN_clear_free(challenge);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute and send a response to the challenge. */
|
||||
respond_to_rsa_challenge(challenge, private->rsa);
|
||||
|
||||
/* Destroy the private key unless it in external hardware. */
|
||||
if (!(private->flags & SSHKEY_FLAG_EXT))
|
||||
key_free(private);
|
||||
|
||||
/* We no longer need the challenge. */
|
||||
BN_clear_free(challenge);
|
||||
|
||||
/* Wait for response from the server. */
|
||||
type = packet_read();
|
||||
if (type == SSH_SMSG_SUCCESS) {
|
||||
debug("RSA authentication accepted by server.");
|
||||
return 1;
|
||||
}
|
||||
if (type != SSH_SMSG_FAILURE)
|
||||
packet_disconnect("Protocol error waiting RSA auth response: %d", type);
|
||||
debug("RSA authentication refused.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries to authenticate the user using combined rhosts or /etc/hosts.equiv
|
||||
* authentication and RSA host authentication.
|
||||
*/
|
||||
static int
|
||||
try_rhosts_rsa_authentication(const char *local_user, Key * host_key)
|
||||
{
|
||||
int type;
|
||||
BIGNUM *challenge;
|
||||
|
||||
debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
|
||||
|
||||
/* Tell the server that we are willing to authenticate using this key. */
|
||||
packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
|
||||
packet_put_cstring(local_user);
|
||||
packet_put_int(BN_num_bits(host_key->rsa->n));
|
||||
packet_put_bignum(host_key->rsa->e);
|
||||
packet_put_bignum(host_key->rsa->n);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
/* Wait for server's response. */
|
||||
type = packet_read();
|
||||
|
||||
/* The server responds with failure if it doesn't admit our
|
||||
.rhosts authentication or doesn't know our host key. */
|
||||
if (type == SSH_SMSG_FAILURE) {
|
||||
debug("Server refused our rhosts authentication or host key.");
|
||||
return 0;
|
||||
}
|
||||
/* Otherwise, the server should respond with a challenge. */
|
||||
if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
|
||||
packet_disconnect("Protocol error during RSA authentication: %d", type);
|
||||
|
||||
/* Get the challenge from the packet. */
|
||||
if ((challenge = BN_new()) == NULL)
|
||||
fatal("try_rhosts_rsa_authentication: BN_new failed");
|
||||
packet_get_bignum(challenge);
|
||||
packet_check_eom();
|
||||
|
||||
debug("Received RSA challenge for host key from server.");
|
||||
|
||||
/* Compute a response to the challenge. */
|
||||
respond_to_rsa_challenge(challenge, host_key->rsa);
|
||||
|
||||
/* We no longer need the challenge. */
|
||||
BN_clear_free(challenge);
|
||||
|
||||
/* Wait for response from the server. */
|
||||
type = packet_read();
|
||||
if (type == SSH_SMSG_SUCCESS) {
|
||||
debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
|
||||
return 1;
|
||||
}
|
||||
if (type != SSH_SMSG_FAILURE)
|
||||
packet_disconnect("Protocol error waiting RSA auth response: %d", type);
|
||||
debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries to authenticate with any string-based challenge/response system.
|
||||
* Note that the client code is not tied to s/key or TIS.
|
||||
*/
|
||||
static int
|
||||
try_challenge_response_authentication(void)
|
||||
{
|
||||
int type, i;
|
||||
u_int clen;
|
||||
char prompt[1024];
|
||||
char *challenge, *response;
|
||||
|
||||
debug("Doing challenge response authentication.");
|
||||
|
||||
for (i = 0; i < options.number_of_password_prompts; i++) {
|
||||
/* request a challenge */
|
||||
packet_start(SSH_CMSG_AUTH_TIS);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
type = packet_read();
|
||||
if (type != SSH_SMSG_FAILURE &&
|
||||
type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
|
||||
packet_disconnect("Protocol error: got %d in response "
|
||||
"to SSH_CMSG_AUTH_TIS", type);
|
||||
}
|
||||
if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
|
||||
debug("No challenge.");
|
||||
return 0;
|
||||
}
|
||||
challenge = packet_get_string(&clen);
|
||||
packet_check_eom();
|
||||
snprintf(prompt, sizeof prompt, "%s%s", challenge,
|
||||
strchr(challenge, '\n') ? "" : "\nResponse: ");
|
||||
free(challenge);
|
||||
if (i != 0)
|
||||
error("Permission denied, please try again.");
|
||||
if (options.cipher == SSH_CIPHER_NONE)
|
||||
logit("WARNING: Encryption is disabled! "
|
||||
"Response will be transmitted in clear text.");
|
||||
response = read_passphrase(prompt, 0);
|
||||
if (strcmp(response, "") == 0) {
|
||||
free(response);
|
||||
break;
|
||||
}
|
||||
packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
|
||||
ssh_put_password(response);
|
||||
explicit_bzero(response, strlen(response));
|
||||
free(response);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
type = packet_read();
|
||||
if (type == SSH_SMSG_SUCCESS)
|
||||
return 1;
|
||||
if (type != SSH_SMSG_FAILURE)
|
||||
packet_disconnect("Protocol error: got %d in response "
|
||||
"to SSH_CMSG_AUTH_TIS_RESPONSE", type);
|
||||
}
|
||||
/* failure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries to authenticate with plain passwd authentication.
|
||||
*/
|
||||
static int
|
||||
try_password_authentication(char *prompt)
|
||||
{
|
||||
int type, i;
|
||||
char *password;
|
||||
|
||||
debug("Doing password authentication.");
|
||||
if (options.cipher == SSH_CIPHER_NONE)
|
||||
logit("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
|
||||
for (i = 0; i < options.number_of_password_prompts; i++) {
|
||||
if (i != 0)
|
||||
error("Permission denied, please try again.");
|
||||
password = read_passphrase(prompt, 0);
|
||||
packet_start(SSH_CMSG_AUTH_PASSWORD);
|
||||
ssh_put_password(password);
|
||||
explicit_bzero(password, strlen(password));
|
||||
free(password);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
type = packet_read();
|
||||
if (type == SSH_SMSG_SUCCESS)
|
||||
return 1;
|
||||
if (type != SSH_SMSG_FAILURE)
|
||||
packet_disconnect("Protocol error: got %d in response to passwd auth", type);
|
||||
}
|
||||
/* failure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SSH1 key exchange
|
||||
*/
|
||||
void
|
||||
ssh_kex(char *host, struct sockaddr *hostaddr)
|
||||
{
|
||||
int i;
|
||||
BIGNUM *key;
|
||||
Key *host_key, *server_key;
|
||||
int bits, rbits;
|
||||
int ssh_cipher_default = SSH_CIPHER_3DES;
|
||||
u_char session_key[SSH_SESSION_KEY_LENGTH];
|
||||
u_char cookie[8];
|
||||
u_int supported_ciphers;
|
||||
u_int server_flags, client_flags;
|
||||
|
||||
debug("Waiting for server public key.");
|
||||
|
||||
/* Wait for a public key packet from the server. */
|
||||
packet_read_expect(SSH_SMSG_PUBLIC_KEY);
|
||||
|
||||
/* Get cookie from the packet. */
|
||||
for (i = 0; i < 8; i++)
|
||||
cookie[i] = packet_get_char();
|
||||
|
||||
/* Get the public key. */
|
||||
if ((server_key = key_new(KEY_RSA1)) == NULL)
|
||||
fatal("%s: key_new(KEY_RSA1) failed", __func__);
|
||||
bits = packet_get_int();
|
||||
packet_get_bignum(server_key->rsa->e);
|
||||
packet_get_bignum(server_key->rsa->n);
|
||||
|
||||
rbits = BN_num_bits(server_key->rsa->n);
|
||||
if (bits != rbits) {
|
||||
logit("Warning: Server lies about size of server public key: "
|
||||
"actual size is %d bits vs. announced %d.", rbits, bits);
|
||||
logit("Warning: This may be due to an old implementation of ssh.");
|
||||
}
|
||||
/* Get the host key. */
|
||||
if ((host_key = key_new(KEY_RSA1)) == NULL)
|
||||
fatal("%s: key_new(KEY_RSA1) failed", __func__);
|
||||
bits = packet_get_int();
|
||||
packet_get_bignum(host_key->rsa->e);
|
||||
packet_get_bignum(host_key->rsa->n);
|
||||
|
||||
rbits = BN_num_bits(host_key->rsa->n);
|
||||
if (bits != rbits) {
|
||||
logit("Warning: Server lies about size of server host key: "
|
||||
"actual size is %d bits vs. announced %d.", rbits, bits);
|
||||
logit("Warning: This may be due to an old implementation of ssh.");
|
||||
}
|
||||
|
||||
/* Get protocol flags. */
|
||||
server_flags = packet_get_int();
|
||||
packet_set_protocol_flags(server_flags);
|
||||
|
||||
supported_ciphers = packet_get_int();
|
||||
supported_authentications = packet_get_int();
|
||||
packet_check_eom();
|
||||
|
||||
debug("Received server public key (%d bits) and host key (%d bits).",
|
||||
BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n));
|
||||
|
||||
if (verify_host_key(host, hostaddr, host_key) == -1)
|
||||
fatal("Host key verification failed.");
|
||||
|
||||
client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
|
||||
|
||||
derive_ssh1_session_id(host_key->rsa->n, server_key->rsa->n, cookie, session_id);
|
||||
|
||||
/*
|
||||
* Generate an encryption key for the session. The key is a 256 bit
|
||||
* random number, interpreted as a 32-byte key, with the least
|
||||
* significant 8 bits being the first byte of the key.
|
||||
*/
|
||||
arc4random_buf(session_key, sizeof(session_key));
|
||||
|
||||
/*
|
||||
* According to the protocol spec, the first byte of the session key
|
||||
* is the highest byte of the integer. The session key is xored with
|
||||
* the first 16 bytes of the session id.
|
||||
*/
|
||||
if ((key = BN_new()) == NULL)
|
||||
fatal("ssh_kex: BN_new failed");
|
||||
if (BN_set_word(key, 0) == 0)
|
||||
fatal("ssh_kex: BN_set_word failed");
|
||||
for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
|
||||
if (BN_lshift(key, key, 8) == 0)
|
||||
fatal("ssh_kex: BN_lshift failed");
|
||||
if (i < 16) {
|
||||
if (BN_add_word(key, session_key[i] ^ session_id[i])
|
||||
== 0)
|
||||
fatal("ssh_kex: BN_add_word failed");
|
||||
} else {
|
||||
if (BN_add_word(key, session_key[i]) == 0)
|
||||
fatal("ssh_kex: BN_add_word failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt the integer using the public key and host key of the
|
||||
* server (key with smaller modulus first).
|
||||
*/
|
||||
if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) {
|
||||
/* Public key has smaller modulus. */
|
||||
if (BN_num_bits(host_key->rsa->n) <
|
||||
BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
|
||||
fatal("respond_to_rsa_challenge: host_key %d < server_key %d + "
|
||||
"SSH_KEY_BITS_RESERVED %d",
|
||||
BN_num_bits(host_key->rsa->n),
|
||||
BN_num_bits(server_key->rsa->n),
|
||||
SSH_KEY_BITS_RESERVED);
|
||||
}
|
||||
if (rsa_public_encrypt(key, key, server_key->rsa) != 0 ||
|
||||
rsa_public_encrypt(key, key, host_key->rsa) != 0)
|
||||
fatal("%s: rsa_public_encrypt failed", __func__);
|
||||
} else {
|
||||
/* Host key has smaller modulus (or they are equal). */
|
||||
if (BN_num_bits(server_key->rsa->n) <
|
||||
BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
|
||||
fatal("respond_to_rsa_challenge: server_key %d < host_key %d + "
|
||||
"SSH_KEY_BITS_RESERVED %d",
|
||||
BN_num_bits(server_key->rsa->n),
|
||||
BN_num_bits(host_key->rsa->n),
|
||||
SSH_KEY_BITS_RESERVED);
|
||||
}
|
||||
if (rsa_public_encrypt(key, key, host_key->rsa) != 0 ||
|
||||
rsa_public_encrypt(key, key, server_key->rsa) != 0)
|
||||
fatal("%s: rsa_public_encrypt failed", __func__);
|
||||
}
|
||||
|
||||
/* Destroy the public keys since we no longer need them. */
|
||||
key_free(server_key);
|
||||
key_free(host_key);
|
||||
|
||||
if (options.cipher == SSH_CIPHER_NOT_SET) {
|
||||
if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default))
|
||||
options.cipher = ssh_cipher_default;
|
||||
} else if (options.cipher == SSH_CIPHER_INVALID ||
|
||||
!(cipher_mask_ssh1(1) & (1 << options.cipher))) {
|
||||
logit("No valid SSH1 cipher, using %.100s instead.",
|
||||
cipher_name(ssh_cipher_default));
|
||||
options.cipher = ssh_cipher_default;
|
||||
}
|
||||
/* Check that the selected cipher is supported. */
|
||||
if (!(supported_ciphers & (1 << options.cipher)))
|
||||
fatal("Selected cipher type %.100s not supported by server.",
|
||||
cipher_name(options.cipher));
|
||||
|
||||
debug("Encryption type: %.100s", cipher_name(options.cipher));
|
||||
|
||||
/* Send the encrypted session key to the server. */
|
||||
packet_start(SSH_CMSG_SESSION_KEY);
|
||||
packet_put_char(options.cipher);
|
||||
|
||||
/* Send the cookie back to the server. */
|
||||
for (i = 0; i < 8; i++)
|
||||
packet_put_char(cookie[i]);
|
||||
|
||||
/* Send and destroy the encrypted encryption key integer. */
|
||||
packet_put_bignum(key);
|
||||
BN_clear_free(key);
|
||||
|
||||
/* Send protocol flags. */
|
||||
packet_put_int(client_flags);
|
||||
|
||||
/* Send the packet now. */
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
debug("Sent encrypted session key.");
|
||||
|
||||
/* Set the encryption key. */
|
||||
packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher);
|
||||
|
||||
/*
|
||||
* We will no longer need the session key here.
|
||||
* Destroy any extra copies.
|
||||
*/
|
||||
explicit_bzero(session_key, sizeof(session_key));
|
||||
|
||||
/*
|
||||
* Expect a success message from the server. Note that this message
|
||||
* will be received in encrypted form.
|
||||
*/
|
||||
packet_read_expect(SSH_SMSG_SUCCESS);
|
||||
|
||||
debug("Received encrypted confirmation.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticate user
|
||||
*/
|
||||
void
|
||||
ssh_userauth1(const char *local_user, const char *server_user, char *host,
|
||||
Sensitive *sensitive)
|
||||
{
|
||||
int i, type;
|
||||
|
||||
if (supported_authentications == 0)
|
||||
fatal("ssh_userauth1: server supports no auth methods");
|
||||
|
||||
/* Send the name of the user to log in as on the server. */
|
||||
packet_start(SSH_CMSG_USER);
|
||||
packet_put_cstring(server_user);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
/*
|
||||
* The server should respond with success if no authentication is
|
||||
* needed (the user has no password). Otherwise the server responds
|
||||
* with failure.
|
||||
*/
|
||||
type = packet_read();
|
||||
|
||||
/* check whether the connection was accepted without authentication. */
|
||||
if (type == SSH_SMSG_SUCCESS)
|
||||
goto success;
|
||||
if (type != SSH_SMSG_FAILURE)
|
||||
packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type);
|
||||
|
||||
/*
|
||||
* Try .rhosts or /etc/hosts.equiv authentication with RSA host
|
||||
* authentication.
|
||||
*/
|
||||
if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
|
||||
options.rhosts_rsa_authentication) {
|
||||
for (i = 0; i < sensitive->nkeys; i++) {
|
||||
if (sensitive->keys[i] != NULL &&
|
||||
sensitive->keys[i]->type == KEY_RSA1 &&
|
||||
try_rhosts_rsa_authentication(local_user,
|
||||
sensitive->keys[i]))
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
/* Try RSA authentication if the server supports it. */
|
||||
if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
|
||||
options.rsa_authentication) {
|
||||
/*
|
||||
* Try RSA authentication using the authentication agent. The
|
||||
* agent is tried first because no passphrase is needed for
|
||||
* it, whereas identity files may require passphrases.
|
||||
*/
|
||||
if (try_agent_authentication())
|
||||
goto success;
|
||||
|
||||
/* Try RSA authentication for each identity. */
|
||||
for (i = 0; i < options.num_identity_files; i++)
|
||||
if (options.identity_keys[i] != NULL &&
|
||||
options.identity_keys[i]->type == KEY_RSA1 &&
|
||||
try_rsa_authentication(i))
|
||||
goto success;
|
||||
}
|
||||
/* Try challenge response authentication if the server supports it. */
|
||||
if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
|
||||
options.challenge_response_authentication && !options.batch_mode) {
|
||||
if (try_challenge_response_authentication())
|
||||
goto success;
|
||||
}
|
||||
/* Try password authentication if the server supports it. */
|
||||
if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
|
||||
options.password_authentication && !options.batch_mode) {
|
||||
char prompt[80];
|
||||
|
||||
snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
|
||||
server_user, host);
|
||||
if (try_password_authentication(prompt))
|
||||
goto success;
|
||||
}
|
||||
/* All authentication methods have failed. Exit with an error message. */
|
||||
fatal("Permission denied.");
|
||||
/* NOTREACHED */
|
||||
|
||||
success:
|
||||
return; /* need statement after label */
|
||||
}
|
||||
|
||||
#endif /* WITH_SSH1 */
|
Loading…
x
Reference in New Issue
Block a user