#8 Rebase to OpenSSH 8.0p1
Closed 5 years ago by jjelen. Opened 5 years ago by jjelen.
rpms/ jjelen/openssh master  into  master

file modified
+2
@@ -34,3 +34,5 @@ 

  /openssh-7.8p1.tar.gz.asc

  /openssh-7.9p1.tar.gz

  /openssh-7.9p1.tar.gz.asc

+ /openssh-8.0p1.tar.gz

+ /openssh-8.0p1.tar.gz.asc

@@ -1,21 +0,0 @@ 

- diff -up openssh-6.1p1/sshconnect2.c.canohost openssh-6.1p1/sshconnect2.c

- --- openssh-6.1p1/sshconnect2.c.canohost	2012-10-30 10:52:59.593301692 +0100

- +++ openssh-6.1p1/sshconnect2.c	2012-10-30 11:01:12.870301632 +0100

- @@ -699,12 +699,15 @@ userauth_gssapi(Authctxt *authctxt)

-  	static u_int mech = 0;

-  	OM_uint32 min;

-  	int r, ok = 0;

- -	const char *gss_host;

- +	const char *gss_host = NULL;

-  

-  	if (options.gss_server_identity)

-  		gss_host = options.gss_server_identity;

- -	else if (options.gss_trust_dns)

- +	else if (options.gss_trust_dns) {

-  		gss_host = get_canonical_hostname(active_state, 1);

- +		if (strcmp(gss_host, "UNKNOWN") == 0)

- +			gss_host = authctxt->host;

- +	}

-  	else

-  		gss_host = authctxt->host;

-  

@@ -1,142 +0,0 @@ 

- diff -up openssh-7.4p1/configure.ac.vendor openssh-7.4p1/configure.ac

- --- openssh-7.4p1/configure.ac.vendor	2016-12-23 13:34:51.681253844 +0100

- +++ openssh-7.4p1/configure.ac	2016-12-23 13:34:51.694253847 +0100

- @@ -4930,6 +4930,12 @@ AC_ARG_WITH([lastlog],

-  		fi

-  	]

-  )

- +AC_ARG_ENABLE(vendor-patchlevel,

- +  [  --enable-vendor-patchlevel=TAG  specify a vendor patch level],

- +  [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.])

- +   SSH_VENDOR_PATCHLEVEL="$enableval"],

- +  [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.])

- +   SSH_VENDOR_PATCHLEVEL=none])

-  

-  dnl lastlog, [uw]tmpx? detection

-  dnl  NOTE: set the paths in the platform section to avoid the

- @@ -5194,6 +5200,7 @@ echo "           Translate v4 in v6 hack

-  echo "                  BSD Auth support: $BSD_AUTH_MSG"

-  echo "              Random number source: $RAND_MSG"

-  echo "             Privsep sandbox style: $SANDBOX_STYLE"

- +echo "                Vendor patch level: $SSH_VENDOR_PATCHLEVEL"

-  

-  echo ""

-  

- diff -up openssh-7.4p1/servconf.c.vendor openssh-7.4p1/servconf.c

- --- openssh-7.4p1/servconf.c.vendor	2016-12-19 05:59:41.000000000 +0100

- +++ openssh-7.4p1/servconf.c	2016-12-23 13:36:07.555268628 +0100

- @@ -143,6 +143,7 @@ initialize_server_options(ServerOptions

-  	options->max_authtries = -1;

-  	options->max_sessions = -1;

-  	options->banner = NULL;

- +	options->show_patchlevel = -1;

-  	options->use_dns = -1;

-  	options->client_alive_interval = -1;

-  	options->client_alive_count_max = -1;

- @@ -325,6 +326,8 @@ fill_default_server_options(ServerOption

-  		options->ip_qos_bulk = IPTOS_DSCP_CS1;

-  	if (options->version_addendum == NULL)

-  		options->version_addendum = xstrdup("");

- +	if (options->show_patchlevel == -1)

- +		options->show_patchlevel = 0;

-  	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)

-  		options->fwd_opts.streamlocal_bind_mask = 0177;

-  	if (options->fwd_opts.streamlocal_bind_unlink == -1)

- @@ -402,7 +405,7 @@ typedef enum {

-  	sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,

-  	sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,

-  	sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,

- -	sBanner, sUseDNS, sHostbasedAuthentication,

- +	sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication,

-  	sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,

-  	sHostKeyAlgorithms,

-  	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,

- @@ -528,6 +531,7 @@ static struct {

-  	{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },

-  	{ "maxsessions", sMaxSessions, SSHCFG_ALL },

-  	{ "banner", sBanner, SSHCFG_ALL },

- +	{ "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL },

-  	{ "usedns", sUseDNS, SSHCFG_GLOBAL },

-  	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },

-  	{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },

- @@ -1369,6 +1373,10 @@ process_server_config_line(ServerOptions

-  		intptr = &options->disable_forwarding;

-  		goto parse_flag;

-  

- +	case sShowPatchLevel:

- +		intptr = &options->show_patchlevel;

- +		goto parse_flag;

- +

-  	case sAllowUsers:

-  		while ((arg = strdelim(&cp)) && *arg != '\0') {

-  			if (match_user(NULL, NULL, NULL, arg) == -1)

- @@ -2269,6 +2277,7 @@ dump_config(ServerOptions *o)

-  	dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);

-  	dump_cfg_fmtint(sCompression, o->compression);

-  	dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);

- +	dump_cfg_fmtint(sShowPatchLevel, o->show_patchlevel);

-  	dump_cfg_fmtint(sUseDNS, o->use_dns);

-  	dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);

-  	dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);

- diff -up openssh-7.4p1/servconf.h.vendor openssh-7.4p1/servconf.h

- --- openssh-7.4p1/servconf.h.vendor	2016-12-19 05:59:41.000000000 +0100

- +++ openssh-7.4p1/servconf.h	2016-12-23 13:34:51.694253847 +0100

- @@ -149,6 +149,7 @@ typedef struct {

-  	int	max_authtries;

-  	int	max_sessions;

-  	char   *banner;			/* SSH-2 banner message */

- +	int	show_patchlevel;	/* Show vendor patch level to clients */

-  	int	use_dns;

-  	int	client_alive_interval;	/*

-  					 * poke the client this often to

- diff -up openssh-7.4p1/sshd_config.5.vendor openssh-7.4p1/sshd_config.5

- --- openssh-7.4p1/sshd_config.5.vendor	2016-12-23 13:34:51.695253847 +0100

- +++ openssh-7.4p1/sshd_config.5	2016-12-23 13:37:17.482282253 +0100

- @@ -1334,6 +1334,13 @@ an OpenSSH Key Revocation List (KRL) as

-  .Cm AcceptEnv

-  or

-  .Cm PermitUserEnvironment .

- +.It Cm ShowPatchLevel 

- +Specifies whether 

- +.Nm sshd 

- +will display the patch level of the binary in the identification string. 

- +The patch level is set at compile-time. 

- +The default is 

- +.Dq no . 

-  .It Cm StreamLocalBindMask

-  Sets the octal file creation mode mask

-  .Pq umask

- diff -up openssh-7.4p1/sshd_config.vendor openssh-7.4p1/sshd_config

- --- openssh-7.4p1/sshd_config.vendor	2016-12-23 13:34:51.690253846 +0100

- +++ openssh-7.4p1/sshd_config	2016-12-23 13:34:51.695253847 +0100

- @@ -105,6 +105,7 @@ X11Forwarding yes

-  #Compression delayed

-  #ClientAliveInterval 0

-  #ClientAliveCountMax 3

- +#ShowPatchLevel no

-  #UseDNS no

-  #PidFile /var/run/sshd.pid

-  #MaxStartups 10:30:100

- diff -up openssh-7.4p1/sshd.c.vendor openssh-7.4p1/sshd.c

- --- openssh-7.4p1/sshd.c.vendor	2016-12-23 13:34:51.682253844 +0100

- +++ openssh-7.4p1/sshd.c	2016-12-23 13:38:32.434296856 +0100

- @@ -367,7 +367,8 @@ sshd_exchange_identification(struct ssh

-  	char remote_version[256];	/* Must be at least as big as buf. */

-  

-  	xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n",

- -	    PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,

- +	    PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,

- +	    (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,

-  	    *options.version_addendum == '\0' ? "" : " ",

-  	    options.version_addendum);

-  

- @@ -1650,7 +1651,8 @@ main(int ac, char **av)

-  		exit(1);

-  	}

-  

- -	debug("sshd version %s, %s", SSH_VERSION,

- +	debug("sshd version %s, %s", 

- +		(options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,

-  #ifdef WITH_OPENSSL

-  	    SSLeay_version(SSLEAY_VERSION)

-  #else

@@ -46,7 +46,7 @@ 

   

  +	pmonitor->m_state = "preauth";

  +

-  	authctxt = _authctxt;

+  	authctxt = (Authctxt *)ssh->authctxt;

   	memset(authctxt, 0, sizeof(*authctxt));

   	ssh->authctxt = authctxt;

  @@ -405,6 +407,8 @@ monitor_child_postauth(struct monitor *p
@@ -113,7 +113,7 @@ 

  +void monitor_reinit(struct monitor *, const char *);

   

   struct Authctxt;

-  void monitor_child_preauth(struct Authctxt *, struct monitor *);

+  void monitor_child_preauth(struct ssh *, struct monitor *);

  diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c

  --- openssh-7.4p1/session.c.log-in-chroot	2016-12-23 15:14:33.319168086 +0100

  +++ openssh-7.4p1/session.c	2016-12-23 15:18:18.742211853 +0100

@@ -22,15 +22,15 @@ 

  --- openssh-7.4p1/servconf.c.GSSAPIEnablek5users	2016-12-23 15:18:40.615216100 +0100

  +++ openssh-7.4p1/servconf.c	2016-12-23 15:35:36.354401156 +0100

  @@ -168,6 +168,7 @@ initialize_server_options(ServerOptions

-  	options->gss_strict_acceptor = -1;

   	options->gss_store_rekey = -1;

+  	options->gss_kex_algorithms = NULL;

   	options->use_kuserok = -1;

  +	options->enable_k5users = -1;

   	options->password_authentication = -1;

   	options->kbd_interactive_authentication = -1;

   	options->challenge_response_authentication = -1;

  @@ -345,6 +346,8 @@ fill_default_server_options(ServerOption

-  		options->gss_store_rekey = 0;

+  #endif

   	if (options->use_kuserok == -1)

   		options->use_kuserok = 1;

  +	if (options->enable_k5users == -1)
@@ -44,20 +44,22 @@ 

   	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,

  -	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,

  +	sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,

-  	sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel,

+  	sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey,

+  	sAcceptEnv, sSetEnv, sPermitTunnel,

   	sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,

-  	sUsePrivilegeSeparation, sAllowAgentForwarding,

- @@ -497,12 +500,14 @@ static struct {

-  	{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },

+ @@ -497,14 +500,16 @@ static struct {

   	{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },

   	{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },

+  	{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },

  +	{ "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },

   #else

   	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },

   	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },

+  	{ "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },

   	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },

   	{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },

   	{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },

+  	{ "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },

  +	{ "gssapienablek5users", sUnsupported, SSHCFG_ALL },

   #endif

   	{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },

file modified
+4 -4
@@ -176,17 +176,17 @@ 

  --- openssh-7.4p1/servconf.c.kuserok	2016-12-23 14:36:07.630465944 +0100

  +++ openssh-7.4p1/servconf.c	2016-12-23 15:11:52.278133344 +0100

  @@ -116,6 +116,7 @@ initialize_server_options(ServerOptions

-  	options->gss_cleanup_creds = -1;

   	options->gss_strict_acceptor = -1;

   	options->gss_store_rekey = -1;

+  	options->gss_kex_algorithms = NULL;

  +	options->use_kuserok = -1;

   	options->password_authentication = -1;

   	options->kbd_interactive_authentication = -1;

   	options->challenge_response_authentication = -1;

  @@ -278,6 +279,8 @@ fill_default_server_options(ServerOption

-  		options->gss_strict_acceptor = 1;

-  	if (options->gss_store_rekey == -1)

-  		options->gss_store_rekey = 0;

+  	if (options->gss_kex_algorithms == NULL)

+  		options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);

+  #endif

  +	if (options->use_kuserok == -1)

  +		options->use_kuserok = 1;

   	if (options->password_authentication == -1)

file modified
+8 -8
@@ -20,7 +20,7 @@ 

  --- openssh-7.4p1/monitor.c.coverity	2016-12-23 16:40:26.888788688 +0100

  +++ openssh-7.4p1/monitor.c	2016-12-23 16:40:26.900788691 +0100

  @@ -411,7 +411,7 @@ monitor_child_preauth(Authctxt *_authctx

-  	mm_get_keystate(pmonitor);

+  	mm_get_keystate(ssh, pmonitor);

   

   	/* Drain any buffered messages from the child */

  -	while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
@@ -124,14 +124,14 @@ 

   }

   

  @@ -518,7 +518,7 @@ server_request_tun(void)

+  		debug("%s: invalid tun", __func__);

+  		goto done;

   	}

-  

-  	tun = packet_get_int();

  -	if (auth_opts->force_tun_device != -1) {

  +	if (auth_opts->force_tun_device >= 0) {

-  		if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != tun)

+  		if (tun != SSH_TUNID_ANY &&

+  		    auth_opts->force_tun_device != (int)tun)

   			goto done;

-  		tun = auth_opts->force_tun_device;

  diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c

  --- openssh-7.4p1/sftp.c.coverity	2016-12-19 05:59:41.000000000 +0100

  +++ openssh-7.4p1/sftp.c	2016-12-23 16:40:26.903788691 +0100
@@ -163,7 +163,7 @@ 

  +++ openssh-7.4p1/sshd.c	2016-12-23 16:40:26.904788692 +0100

  @@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt)

   

-  		privsep_preauth_child();

+  		privsep_preauth_child(ssh);

   		setproctitle("%s", "[net]");

  -		if (box != NULL)

  +		if (box != NULL) {
@@ -174,8 +174,8 @@ 

   		return 0;

   	}

  @@ -1386,6 +1388,9 @@ server_accept_loop(int *sock_in, int *so

-  		if (num_listen_socks < 0)

-  			break;

+  			explicit_bzero(rnd, sizeof(rnd));

+  		}

   	}

  +

  +	if (fdset != NULL)

file modified
+13 -3
@@ -40,7 +40,7 @@ 

  diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c

  --- openssh-6.8p1/ssh-cavs.c.kdf-cavs	2015-03-18 11:23:46.348049354 +0100

  +++ openssh-6.8p1/ssh-cavs.c	2015-03-18 11:23:46.348049354 +0100

- @@ -0,0 +1,377 @@

+ @@ -0,0 +1,387 @@

  +/*

  + * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>

  + *
@@ -208,6 +208,7 @@ 

  +{

  +	int ret = 0;

  +	struct kex kex;

+ +	struct sshbuf *Kb = NULL;

  +	BIGNUM *Kbn = NULL;

  +	int mode = 0;

  +	struct newkeys *ctoskeys;
@@ -222,10 +223,17 @@ 

  +	Kbn = BN_new();

  +	BN_bin2bn(test->K, test->Klen, Kbn);

  +	if (!Kbn) {

- +		printf("cannot convert K into BIGNUM\n");

+ +		printf("cannot convert K into bignum\n");

  +		ret = 1;

  +		goto out;

  +	}

+ +	Kb = sshbuf_new();

+ +	if (!Kb) {

+ +		printf("cannot convert K into sshbuf\n");

+ +		ret = 1;

+ +		goto out;

+ +	}

+ +	sshbuf_put_bignum2(Kb, Kbn);

  +

  +	kex.session_id = test->session_id;

  +	kex.session_id_len = test->session_id_len;
@@ -285,7 +293,7 @@ 

  +		goto out;

  +	}

  +	ssh->kex = &kex;

- +	kex_derive_keys_bn(ssh, test->H, test->Hlen, Kbn);

+ +	kex_derive_keys(ssh, test->H, test->Hlen, Kb);

  +

  +	ctoskeys = kex.newkeys[0];

  +	stockeys = kex.newkeys[1];
@@ -321,6 +329,8 @@ 

  +out:

  +	if (Kbn)

  +		BN_free(Kbn);

+ +	if (Kb)

+ +		sshbuf_free(Kb);

  +	if (ssh)

  +		ssh_packet_close(ssh);

  +	return ret;

@@ -10,18 +10,3 @@ 

   	dump_cfg_string(sForceCommand, o->adm_forced_command);

   	dump_cfg_string(sChrootDirectory, o->chroot_directory);

   	dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);

- diff -up openssh/ssh.1.sshdt openssh/ssh.1

- --- openssh/ssh.1.sshdt	2015-06-24 11:42:19.565102807 +0200

- +++ openssh/ssh.1	2015-06-24 11:42:29.042078701 +0200

- @@ -441,7 +441,11 @@ For full details of the options listed b

-  .It GatewayPorts

-  .It GlobalKnownHostsFile

-  .It GSSAPIAuthentication

- +.It GSSAPIKeyExchange

- +.It GSSAPIClientIdentity

-  .It GSSAPIDelegateCredentials

- +.It GSSAPIRenewalForcesRekey

- +.It GSSAPITrustDNS

-  .It HashKnownHosts

-  .It Host

-  .It HostbasedAuthentication

@@ -1,431 +0,0 @@ 

- diff -up openssh-7.0p1/gss-genr.c.gsskexalg openssh-7.0p1/gss-genr.c

- --- openssh-7.0p1/gss-genr.c.gsskexalg	2015-08-19 12:28:38.024518959 +0200

- +++ openssh-7.0p1/gss-genr.c	2015-08-19 12:28:38.078518839 +0200

- @@ -78,7 +78,8 @@ ssh_gssapi_oid_table_ok() {

-   */

-  

-  char *

- -ssh_gssapi_client_mechanisms(const char *host, const char *client) {

- +ssh_gssapi_client_mechanisms(const char *host, const char *client,

- +    const char *kex) {

-  	gss_OID_set gss_supported;

-  	OM_uint32 min_status;

-  

- @@ -86,12 +87,12 @@ ssh_gssapi_client_mechanisms(const char

-  		return NULL;

-  

-  	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,

- -	    host, client));

- +	    host, client, kex));

-  }

-  

-  char *

-  ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,

- -    const char *host, const char *client) {

- +    const char *host, const char *client, const char *kex) {

-  	struct sshbuf *buf;

-  	size_t i;

-  	int oidpos, enclen, r;

- @@ -100,6 +101,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup

-  	char deroid[2];

-  	const EVP_MD *evp_md = EVP_md5();

-  	EVP_MD_CTX *md;

- +	char *s, *cp, *p;

-  

-  	if (gss_enc2oid != NULL) {

-  		for (i = 0; gss_enc2oid[i].encoded != NULL; i++)

- @@ -113,6 +115,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup

-  

-  	md = EVP_MD_CTX_new();

-  	oidpos = 0;

- +	s = cp = xstrdup(kex);

-  	for (i = 0; i < gss_supported->count; i++) {

-  		if (gss_supported->elements[i].length < 128 &&

-  		    (*check)(NULL, &(gss_supported->elements[i]), host, client)) {

- @@ -131,28 +134,25 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup

-  			enclen = __b64_ntop(digest, EVP_MD_size(evp_md),

-  			    encoded, EVP_MD_size(evp_md) * 2);

-  

- -			if (oidpos != 0)

- -				if ((r = sshbuf_put_u8(buf, ',')) != 0)

- -					fatal("%s: buffer error: %s", __func__, ssh_err(r));

- -

- -			if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID,

- -			    sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 ||

- -			    (r = sshbuf_put(buf, encoded, enclen)) != 0 ||

- -			    (r = sshbuf_put_u8(buf, ',')) != 0 ||

- -			    (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID, 

- -			    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 ||

- -			    (r = sshbuf_put(buf, encoded, enclen)) != 0 ||

- -			    (r = sshbuf_put_u8(buf, ',')) != 0 ||

- -			    (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID,

- -			    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 ||

- -			    (r = sshbuf_put(buf, encoded, enclen)) != 0)

- -		 		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +			cp = strncpy(s, kex, strlen(kex));

- +			for ((p = strsep(&cp, ",")); p && *p != '\0';

- +				(p = strsep(&cp, ","))) {

- +				if (sshbuf_len(buf) != 0)

- +					if ((r = sshbuf_put_u8(buf, ',')) != 0)

- +			 			fatal("%s: buffer error: %s",

- +						    __func__, ssh_err(r));

- +				if ((r = sshbuf_put(buf, p, strlen(p))) != 0 ||

- +				    (r = sshbuf_put(buf, encoded, enclen)) != 0)

- +			 		fatal("%s: buffer error: %s",

- +					    __func__, ssh_err(r));

- +			}

-  

-  			gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);

-  			gss_enc2oid[oidpos].encoded = encoded;

-  			oidpos++;

-  		}

-  	}

- +	free(s);

-  	EVP_MD_CTX_free(md);

-  	gss_enc2oid[oidpos].oid = NULL;

-  	gss_enc2oid[oidpos].encoded = NULL;

- diff -up openssh-7.0p1/gss-serv.c.gsskexalg openssh-7.0p1/gss-serv.c

- --- openssh-7.0p1/gss-serv.c.gsskexalg	2015-08-19 12:28:38.024518959 +0200

- +++ openssh-7.0p1/gss-serv.c	2015-08-19 12:28:38.078518839 +0200

- @@ -149,7 +149,8 @@ ssh_gssapi_server_mechanisms() {

-  	if (supported_oids == NULL)

-  		ssh_gssapi_prepare_supported_oids();

-  	return (ssh_gssapi_kex_mechs(supported_oids,

- -	    &ssh_gssapi_server_check_mech, NULL, NULL));

- +	    &ssh_gssapi_server_check_mech, NULL, NULL,

- +	    options.gss_kex_algorithms));

-  }

-  

-  /* Unprivileged */

- diff -up openssh-7.0p1/kex.c.gsskexalg openssh-7.0p1/kex.c

- --- openssh-7.0p1/kex.c.gsskexalg	2015-08-19 12:28:38.078518839 +0200

- +++ openssh-7.0p1/kex.c	2015-08-19 12:30:13.249306371 +0200

- @@ -50,6 +50,7 @@

-  #include "misc.h"

-  #include "dispatch.h"

-  #include "monitor.h"

- +#include "xmalloc.h"

-  

-  #include "ssherr.h"

-  #include "sshbuf.h"

- @@ -232,6 +232,29 @@ kex_assemble_names(const char *def, char

-  	return r;

-  }

-  

- +/* Validate GSS KEX method name list */

- +int

- +gss_kex_names_valid(const char *names)

- +{

- +	char *s, *cp, *p;

- +

- +	if (names == NULL || *names == '\0')

- +		return 0;

- +	s = cp = xstrdup(names);

- +	for ((p = strsep(&cp, ",")); p && *p != '\0';

- +	    (p = strsep(&cp, ","))) {

- +		if (strncmp(p, "gss-", 4) != 0

- +		  || kex_alg_by_name(p) == NULL) {

- +			error("Unsupported KEX algorithm \"%.100s\"", p);

- +			free(s);

- +			return 0;

- +		}

- +	}

- +	debug3("gss kex names ok: [%s]", names);

- +	free(s);

- +	return 1;

- +}

- +

-  /* put algorithm proposal into buffer */

-  int

-  kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])

- diff -up openssh-7.0p1/kex.h.gsskexalg openssh-7.0p1/kex.h

- --- openssh-7.0p1/kex.h.gsskexalg	2015-08-19 12:28:38.078518839 +0200

- +++ openssh-7.0p1/kex.h	2015-08-19 12:30:52.404218958 +0200

- @@ -173,6 +173,7 @@ int	 kex_names_valid(const char *);

-  char	*kex_alg_list(char);

-  char	*kex_names_cat(const char *, const char *);

-  int	 kex_assemble_names(char **, const char *, const char *);

- +int	 gss_kex_names_valid(const char *);

-  

-  int	 kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **);

-  int	 kex_setup(struct ssh *, char *[PROPOSAL_MAX]);

- diff -up openssh-7.0p1/readconf.c.gsskexalg openssh-7.0p1/readconf.c

- --- openssh-7.0p1/readconf.c.gsskexalg	2015-08-19 12:28:38.026518955 +0200

- +++ openssh-7.0p1/readconf.c	2015-08-19 12:31:28.333138747 +0200

- @@ -61,6 +61,7 @@

-  #include "uidswap.h"

-  #include "myproposal.h"

-  #include "digest.h"

- +#include "ssh-gss.h"

-  

-  /* Format of the configuration file:

-  

- @@ -148,7 +149,7 @@ typedef enum {

-  	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,

-  	oAddressFamily, oGssAuthentication, oGssDelegateCreds,

-  	oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,

- -	oGssServerIdentity, 

- +	oGssServerIdentity, oGssKexAlgorithms,

-  	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,

-  	oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,

-  	oHashKnownHosts,

- @@ -200,6 +201,7 @@ static struct {

-  	{ "gssapiclientidentity", oGssClientIdentity },

-  	{ "gssapiserveridentity", oGssServerIdentity },

-  	{ "gssapirenewalforcesrekey", oGssRenewalRekey },

- +	{ "gssapikexalgorithms", oGssKexAlgorithms },

-  # else

-  	{ "gssapiauthentication", oUnsupported },

-  	{ "gssapikeyexchange", oUnsupported },

- @@ -207,6 +209,7 @@ static struct {

-  	{ "gssapitrustdns", oUnsupported },

-  	{ "gssapiclientidentity", oUnsupported },

-  	{ "gssapirenewalforcesrekey", oUnsupported },

- +	{ "gssapikexalgorithms", oUnsupported },

-  #endif

-  #ifdef ENABLE_PKCS11

-  	{ "smartcarddevice", oPKCS11Provider },

- @@ -929,6 +932,18 @@ parse_time:

-  		intptr = &options->gss_renewal_rekey;

-  		goto parse_flag;

-  

- +	case oGssKexAlgorithms:

- +		arg = strdelim(&s);

- +		if (!arg || *arg == '\0')

- +			fatal("%.200s line %d: Missing argument.",

- +			    filename, linenum);

- +		if (!gss_kex_names_valid(arg))

- +			fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.",

- +			    filename, linenum, arg ? arg : "<NONE>");

- +		if (*activep && options->gss_kex_algorithms == NULL)

- +			options->gss_kex_algorithms = xstrdup(arg);

- +		break;

- +

-  	case oBatchMode:

-  		intptr = &options->batch_mode;

-  		goto parse_flag;

- @@ -1638,6 +1653,7 @@ initialize_options(Options * options)

-  	options->gss_renewal_rekey = -1;

-  	options->gss_client_identity = NULL;

-  	options->gss_server_identity = NULL;

- +	options->gss_kex_algorithms = NULL;

-  	options->password_authentication = -1;

-  	options->kbd_interactive_authentication = -1;

-  	options->kbd_interactive_devices = NULL;

- @@ -1773,6 +1789,10 @@ fill_default_options(Options * options)

-  		options->gss_trust_dns = 0;

-  	if (options->gss_renewal_rekey == -1)

-  		options->gss_renewal_rekey = 0;

- +#ifdef GSSAPI

- +	if (options->gss_kex_algorithms == NULL)

- +		options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);

- +#endif

-  	if (options->password_authentication == -1)

-  		options->password_authentication = 1;

-  	if (options->kbd_interactive_authentication == -1)

- @@ -2651,6 +2671,8 @@ dump_client_config(Options *o, const cha

-  	dump_cfg_string(oGssClientIdentity, o->gss_client_identity);

-  	dump_cfg_string(oGssServerIdentity, o->gss_client_identity);

-  	dump_cfg_fmtint(oGssRenewalRekey, o->gss_renewal_rekey);

- +	dump_cfg_string(oGssKexAlgorithms, o->gss_kex_algorithms ?

- +		o->gss_kex_algorithms : GSS_KEX_DEFAULT_KEX);

-  #endif /* GSSAPI */

-  	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);

-  	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);

- diff -up openssh-7.9p1/readconf.h.gsskexalg openssh-7.9p1/readconf.h

- --- openssh-7.9p1/readconf.h.gsskexalg	2018-11-14 09:20:06.616350574 +0100

- +++ openssh-7.9p1/readconf.h	2018-11-14 09:20:06.647350828 +0100

- @@ -46,6 +46,7 @@ typedef struct {

-  	int	gss_renewal_rekey;	/* Credential renewal forces rekey */

-  	char    *gss_client_identity;   /* Principal to initiate GSSAPI with */

-  	char    *gss_server_identity;   /* GSSAPI target principal */

- +	char   *gss_kex_algorithms;	/* GSSAPI kex methods to be offered by client. */

-  	int     password_authentication;	/* Try password

-  						 * authentication. */

-  	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */

- diff -up openssh-7.0p1/servconf.c.gsskexalg openssh-7.0p1/servconf.c

- --- openssh-7.0p1/servconf.c.gsskexalg	2015-08-19 12:28:38.074518847 +0200

- +++ openssh-7.0p1/servconf.c	2015-08-19 12:33:13.599902732 +0200

- @@ -57,6 +57,7 @@

-  #include "auth.h"

-  #include "myproposal.h"

-  #include "digest.h"

- +#include "ssh-gss.h"

-  

-  static void add_listen_addr(ServerOptions *, const char *,

-      const char *, int);

- @@ -121,6 +122,7 @@ initialize_server_options(ServerOptions

-  	options->gss_cleanup_creds = -1;

-  	options->gss_strict_acceptor = -1;

-  	options->gss_store_rekey = -1;

- +	options->gss_kex_algorithms = NULL;

-  	options->use_kuserok = -1;

-  	options->enable_k5users = -1;

-  	options->password_authentication = -1;

- @@ -288,6 +290,10 @@ fill_default_server_options(ServerOption

-  		options->gss_strict_acceptor = 1;

-  	if (options->gss_store_rekey == -1)

-  		options->gss_store_rekey = 0;

- +#ifdef GSSAPI

- +	if (options->gss_kex_algorithms == NULL)

- +		options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);

- +#endif

-  	if (options->use_kuserok == -1)

-  		options->use_kuserok = 1;

-  	if (options->enable_k5users == -1)

- @@ -427,7 +431,7 @@ typedef enum {

-  	sHostKeyAlgorithms,

-  	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,

-  	sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,

- -	sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel,

- +	sGssKeyEx, sGssStoreRekey, sGssKexAlgorithms, sAcceptEnv, sSetEnv, sPermitTunnel,

-  	sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,

-  	sUsePrivilegeSeparation, sAllowAgentForwarding,

-  	sHostCertificate,

- @@ -506,6 +510,7 @@ static struct {

-  	{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },

-  	{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },

-  	{ "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },

- +	{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },

-  #else

-  	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },

-  	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },

- @@ -513,6 +518,7 @@ static struct {

-  	{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },

-  	{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },

-  	{ "gssapienablek5users", sUnsupported, SSHCFG_ALL },

- +	{ "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },

-  #endif

-  	{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },

-  	{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },

- @@ -1273,6 +1279,18 @@ process_server_config_line(ServerOptions

-  		intptr = &options->gss_store_rekey;

-  		goto parse_flag;

-  

- +	case sGssKexAlgorithms:

- +		arg = strdelim(&cp);

- +		if (!arg || *arg == '\0')

- +			fatal("%.200s line %d: Missing argument.",

- +			    filename, linenum);

- +		if (!gss_kex_names_valid(arg))

- +			fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.",

- +			    filename, linenum, arg ? arg : "<NONE>");

- +		if (*activep && options->gss_kex_algorithms == NULL)

- +			options->gss_kex_algorithms = xstrdup(arg);

- +		break;

- +

-  	case sPasswordAuthentication:

-  		intptr = &options->password_authentication;

-  		goto parse_flag;

- @@ -2304,6 +2322,7 @@ dump_config(ServerOptions *o)

-  	dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);

-  	dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);

-  	dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);

- +	dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms);

-  #endif

-  	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);

-  	dump_cfg_fmtint(sKbdInteractiveAuthentication,

- diff -up openssh-7.0p1/servconf.h.gsskexalg openssh-7.0p1/servconf.h

- --- openssh-7.0p1/servconf.h.gsskexalg	2015-08-19 12:28:38.080518834 +0200

- +++ openssh-7.0p1/servconf.h	2015-08-19 12:34:46.328693944 +0200

- @@ -122,6 +122,7 @@ typedef struct {

-  	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */

-  	int     gss_strict_acceptor;	/* If true, restrict the GSSAPI acceptor name */

-  	int 	gss_store_rekey;

- +	char   *gss_kex_algorithms;	/* GSSAPI kex methods to be offered by client. */

-  	int     password_authentication;	/* If true, permit password

-  						 * authentication. */

-  	int     kbd_interactive_authentication;	/* If true, permit */

- diff -up openssh-7.0p1/ssh.1.gsskexalg openssh-7.0p1/ssh.1

- --- openssh-7.0p1/ssh.1.gsskexalg	2015-08-19 12:28:38.081518832 +0200

- +++ openssh-7.0p1/ssh.1	2015-08-19 12:35:31.741591692 +0200

- @@ -496,6 +496,7 @@ For full details of the options listed b

-  .It GSSAPIDelegateCredentials

-  .It GSSAPIRenewalForcesRekey

-  .It GSSAPITrustDNS

- +.It GSSAPIKexAlgorithms

-  .It HashKnownHosts

-  .It Host

-  .It HostbasedAuthentication

- diff -up openssh-7.0p1/ssh_config.5.gsskexalg openssh-7.0p1/ssh_config.5

- --- openssh-7.0p1/ssh_config.5.gsskexalg	2015-08-19 12:28:38.028518950 +0200

- +++ openssh-7.0p1/ssh_config.5	2015-08-19 12:28:38.082518830 +0200

- @@ -786,6 +786,18 @@ command line will be passed untouched to

-  command line will be passed untouched to the GSSAPI library.

-  The default is

-  .Dq no .

- +.It Cm GSSAPIKexAlgorithms

- +The list of key exchange algorithms that are offered for GSSAPI

- +key exchange. Possible values are

- +.Bd -literal -offset 3n

- +gss-gex-sha1-,

- +gss-group1-sha1-,

- +gss-group14-sha1-

- +.Ed

- +.Pp

- +The default is

- +.Dq gss-gex-sha1-,gss-group14-sha1- .

- +This option only applies to protocol version 2 connections using GSSAPI.

-  .It Cm HashKnownHosts

-  Indicates that

-  .Xr ssh 1

- diff -up openssh-7.0p1/sshconnect2.c.gsskexalg openssh-7.0p1/sshconnect2.c

- --- openssh-7.0p1/sshconnect2.c.gsskexalg	2015-08-19 12:28:38.045518912 +0200

- +++ openssh-7.0p1/sshconnect2.c	2015-08-19 12:28:38.081518832 +0200

- @@ -179,7 +179,8 @@ ssh_kex2(char *host, struct sockaddr *ho

-  		else

-  			gss_host = host;

-  

- -		gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);

- +		gss = ssh_gssapi_client_mechanisms(gss_host,

- +		    options.gss_client_identity, options.gss_kex_algorithms);

-  		if (gss) {

-  			debug("Offering GSSAPI proposal: %s", gss);

-  			xasprintf(&options.kex_algorithms,

- --- openssh-7.1p1/sshd_config.5.gsskexalg	2015-12-10 15:32:48.105418092 +0100

- +++ openssh-7.1p1/sshd_config.5	2015-12-10 15:33:47.771279548 +0100

- @@ -663,6 +663,18 @@ or updated credentials from a compatible

-  For this to work

-  .Cm GSSAPIKeyExchange

-  needs to be enabled in the server and also used by the client.

- +.It Cm GSSAPIKexAlgorithms

- +The list of key exchange algorithms that are accepted by GSSAPI

- +key exchange. Possible values are

- +.Bd -literal -offset 3n

- +gss-gex-sha1-,

- +gss-group1-sha1-,

- +gss-group14-sha1-

- +.Ed

- +.Pp

- +The default is

- +.Dq gss-gex-sha1-,gss-group14-sha1- .

- +This option only applies to protocol version 2 connections using GSSAPI.

-  .It Cm HostbasedAcceptedKeyTypes

-  Specifies the key types that will be accepted for hostbased authentication

-  as a list of comma-separated patterns.

- diff -up openssh-7.0p1/ssh-gss.h.gsskexalg openssh-7.0p1/ssh-gss.h

- --- openssh-7.0p1/ssh-gss.h.gsskexalg	2015-08-19 12:28:38.031518944 +0200

- +++ openssh-7.0p1/ssh-gss.h	2015-08-19 12:28:38.081518832 +0200

- @@ -76,6 +76,10 @@ extern char **k5users_allowed_cmds;

-  #define KEX_GSS_GRP14_SHA1_ID				"gss-group14-sha1-"

-  #define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"

-  

- +#define        GSS_KEX_DEFAULT_KEX \

- +	KEX_GSS_GEX_SHA1_ID "," \

- +	KEX_GSS_GRP14_SHA1_ID

- +

-  typedef struct {

-  	char *envvar;

-  	char *envval;

- @@ -147,9 +151,9 @@ int ssh_gssapi_credentials_updated(Gssct

-  /* In the server */

-  typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 

-      const char *);

- -char *ssh_gssapi_client_mechanisms(const char *, const char *);

- +char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *);

-  char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,

- -    const char *);

- +    const char *, const char *);

-  gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);

-  int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 

-      const char *);

@@ -1,52 +0,0 @@ 

- diff -up openssh-7.4p1/ssh_config.5.gss-docs openssh-7.4p1/ssh_config.5

- --- openssh-7.4p1/ssh_config.5.gss-docs	2016-12-23 14:28:34.051714486 +0100

- +++ openssh-7.4p1/ssh_config.5	2016-12-23 14:34:24.568522417 +0100

- @@ -765,10 +765,19 @@ The default is

-  If set to 

-  .Dq yes

-  then renewal of the client's GSSAPI credentials will force the rekeying of the

- -ssh connection. With a compatible server, this can delegate the renewed 

- +ssh connection. With a compatible server, this will delegate the renewed 

-  credentials to a session on the server.

- +.Pp

- +Checks are made to ensure that credentials are only propagated when the new

- +credentials match the old ones on the originating client and where the

- +receiving server still has the old set in its cache.

- +.Pp

-  The default is

-  .Dq no .

- +.Pp

- +For this to work

- +.Cm GSSAPIKeyExchange

- +needs to be enabled in the server and also used by the client.

-  .It Cm GSSAPIServerIdentity

-  If set, specifies the GSSAPI server identity that ssh should expect when 

-  connecting to the server. The default is unset, which means that the

- @@ -776,9 +785,11 @@ expected GSSAPI server identity will be

-  hostname.

-  .It Cm GSSAPITrustDns

-  Set to 

- -.Dq yes to indicate that the DNS is trusted to securely canonicalize

- +.Dq yes

- +to indicate that the DNS is trusted to securely canonicalize

-  the name of the host being connected to. If 

- -.Dq no, the hostname entered on the

- +.Dq no ,

- +the hostname entered on the

-  command line will be passed untouched to the GSSAPI library.

-  The default is

-  .Dq no .

- diff -up openssh-7.4p1/sshd_config.5.gss-docs openssh-7.4p1/sshd_config.5

- --- openssh-7.4p1/sshd_config.5.gss-docs	2016-12-23 14:28:34.043714490 +0100

- +++ openssh-7.4p1/sshd_config.5	2016-12-23 14:28:34.051714486 +0100

- @@ -652,6 +652,10 @@ Controls whether the user's GSSAPI crede

-  successful connection rekeying. This option can be used to accepted renewed 

-  or updated credentials from a compatible client. The default is

-  .Dq no .

- +.Pp

- +For this to work

- +.Cm GSSAPIKeyExchange

- +needs to be enabled in the server and also used by the client.

-  .It Cm HostbasedAcceptedKeyTypes

-  Specifies the key types that will be accepted for hostbased authentication

-  as a list of comma-separated patterns.

@@ -56,9 +56,9 @@ 

  --- openssh-7.4p1/monitor_wrap.h.audit-race	2016-12-23 16:35:52.694685771 +0100

  +++ openssh-7.4p1/monitor_wrap.h	2016-12-23 16:35:52.698685772 +0100

  @@ -83,6 +83,8 @@ void mm_audit_unsupported_body(int);

-  void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t);

-  void mm_audit_session_key_free_body(int, pid_t, uid_t);

-  void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t);

+  void mm_audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t);

+  void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t);

+  void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t);

  +int mm_forward_audit_messages(int);

  +void mm_set_monitor_pipe(int);

   #endif
@@ -82,7 +82,7 @@ 

   	return 1;

   }

   

- +void child_destory_sensitive_data();

+ +void child_destory_sensitive_data(struct ssh *ssh);

  +

   #define USE_PIPES 1

   /*
@@ -91,7 +91,7 @@ 

   		close(err[0]);

   #endif

   

- +		child_destory_sensitive_data();

+ +		child_destory_sensitive_data(ssh);

  +

   		/* Do processing for the child (exec command etc). */

   		do_child(ssh, s, command);
@@ -101,7 +101,7 @@ 

   		close(ttyfd);

   

  +		/* Do this early, so we will not block large MOTDs */

- +		child_destory_sensitive_data();

+ +		child_destory_sensitive_data(ssh);

  +

   		/* record login, etc. similar to login(1) */

   #ifndef HAVE_OSF_SIA
@@ -109,7 +109,7 @@ 

  @@ -717,6 +728,8 @@ do_exec(Session *s, const char *command)

   	}

   	if (s->command != NULL && s->ptyfd == -1)

-  		s->command_handle = PRIVSEP(audit_run_command(s->command));

+  		s->command_handle = PRIVSEP(audit_run_command(ssh, s->command));

  +	if (pipe(paudit) < 0)

  +		fatal("pipe: %s", strerror(errno));

   #endif
@@ -141,7 +141,7 @@ 

   }

   

  +void

- +child_destory_sensitive_data()

+ +child_destory_sensitive_data(struct ssh *ssh)

  +{

  +#ifdef SSH_AUDIT_EVENTS

  +	int pparent = paudit[1];
@@ -152,15 +152,15 @@ 

  +#endif

  +

  +	/* remove hostkey from the child's memory */

- +	destroy_sensitive_data(use_privsep);

+ +	destroy_sensitive_data(ssh, use_privsep);

  +	/*

  +	 * We can audit this, because we hacked the pipe to direct the

  +	 * messages over postauth child. But this message requires answer

  +	 * which we can't do using one-way pipe.

  +	 */

- +	packet_destroy_all(0, 1);

+ +	packet_destroy_all(ssh, 0, 1);

  +	/* XXX this will clean the rest but should not audit anymore */

- +	/* packet_clear_keys(); */

+ +	/* packet_clear_keys(ssh); */

  +

  +#ifdef SSH_AUDIT_EVENTS

  +	/* Notify parent that we are done */
@@ -172,15 +172,15 @@ 

    * Performs common processing for the child, such as setting up the

    * environment, closing extra file descriptors, setting the user and group

  @@ -1554,13 +1608,6 @@ do_child(Session *s, const char *command

-  		pw = s->pw;

-  	}

+  

+  	sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));

   

  -	/* remove hostkey from the child's memory */

- -	destroy_sensitive_data(1);

- -	packet_clear_keys();

+ -	destroy_sensitive_data(ssh, 1);

+ -	ssh_packet_clear_keys(ssh);

  -	/* Don't audit this - both us and the parent would be talking to the

  -	   monitor over a single socket, with no synchronization. */

- -	packet_destroy_all(0, 1);

+ -	packet_destroy_all(ssh, 0, 1);

  -

   	/* Force a password change */

   	if (s->authctxt->force_pwchange) {

@@ -2,10 +2,11 @@ 

  index 2b02a04..19b9364 100644

  --- a/auth-krb5.c

  +++ b/auth-krb5.c

- @@ -375,6 +375,22 @@ cleanup:

-  	return -1;

+ @@ -375,5 +375,21 @@ cleanup:

+  		return (krb5_cc_resolve(ctx, ccname, ccache));

+  	}

   }

-  

+ +

  +/*

  + * Reads  k5login_directory  option from the  krb5.conf

  + */
@@ -21,10 +22,8 @@ 

  +	return profile_get_string(p, "libdefaults", "k5login_directory", NULL, NULL,

  +		k5login_directory);

  +}

- +

-  krb5_error_code

-  ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {

-  	profile_t p;

+  #endif /* !HEIMDAL */

+  #endif /* KRB5 */

  diff --git a/auth.h b/auth.h

  index f9d191c..c432d2f 100644

  --- a/auth.h

@@ -1,1377 +0,0 @@ 

- From 6ff8f667f792052fd47689c3e421fcd6ddca1cd0 Mon Sep 17 00:00:00 2001

- From: Jakub Jelen <jjelen@redhat.com>

- Date: Fri, 25 Aug 2017 19:15:48 +0200

- Subject: [PATCH 1/3] GSSAPI Key exchange methods with DH and SHA2

- 

- ---

-  gss-genr.c         | 10 ++++++++++

-  kex.c              |  2 ++

-  kex.h              |  2 ++

-  kexgssc.c          |  6 ++++++

-  kexgsss.c          |  6 ++++++

-  monitor.c          |  2 ++

-  regress/kextype.sh |  4 +++-

-  regress/rekey.sh   |  8 ++++++--

-  ssh-gss.h          |  2 ++

-  ssh_config.5       |  4 +++-

-  sshconnect2.c      |  2 ++

-  sshd.c             |  2 ++

-  sshd_config.5      |  4 +++-

-  13 files changed, 49 insertions(+), 5 deletions(-)

- 

- diff --git a/gss-genr.c b/gss-genr.c

- index dc63682d..c6eff3d7 100644

- --- a/gss-genr.c

- +++ b/gss-genr.c

- @@ -183,6 +183,16 @@ ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {

-  			return GSS_C_NO_OID;

-  		name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;

-  		break;

- +	case KEX_GSS_GRP14_SHA256:

- +		if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA256_ID))

- +			return GSS_C_NO_OID;

- +		name += sizeof(KEX_GSS_GRP14_SHA256_ID) - 1;

- +		break;

- +	case KEX_GSS_GRP16_SHA512:

- +		if (strlen(name) < sizeof(KEX_GSS_GRP16_SHA512_ID))

- +			return GSS_C_NO_OID;

- +		name += sizeof(KEX_GSS_GRP16_SHA512_ID) - 1;

- +		break;

-  	case KEX_GSS_GEX_SHA1:

-  		if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))

-  			return GSS_C_NO_OID;

- diff --git a/kex.c b/kex.c

- index 63e028fa..e798fecb 100644

- --- a/kex.c

- +++ b/kex.c

- @@ -112,6 +112,8 @@ static const struct kexalg kexalgs[] = {

-  	{ KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 },

-  	{ KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },

-  	{ KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },

- +	{ KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },

- +	{ KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },

-  #endif

-  	{ NULL, -1, -1, -1},

-  };

- diff --git a/kex.h b/kex.h

- index 8a2b37c5..f27958ae 100644

- --- a/kex.h

- +++ b/kex.h

- @@ -102,6 +102,8 @@ enum kex_exchange {

-  #ifdef GSSAPI

-  	KEX_GSS_GRP1_SHA1,

-  	KEX_GSS_GRP14_SHA1,

- +	KEX_GSS_GRP14_SHA256,

- +	KEX_GSS_GRP16_SHA512,

-  	KEX_GSS_GEX_SHA1,

-  #endif

-  	KEX_MAX

- diff --git a/kexgssc.c b/kexgssc.c

- index 132df8b5..ed23f06d 100644

- --- a/kexgssc.c

- +++ b/kexgssc.c

- @@ -88,8 +88,12 @@ kexgss_client(struct ssh *ssh) {

-  		dh = dh_new_group1();

-  		break;

-  	case KEX_GSS_GRP14_SHA1:

- +	case KEX_GSS_GRP14_SHA256:

-  		dh = dh_new_group14();

-  		break;

- +	case KEX_GSS_GRP16_SHA512:

- +		dh = dh_new_group16();

- +		break;

-  	case KEX_GSS_GEX_SHA1:

-  		debug("Doing group exchange\n");

-  		nbits = dh_estimate(ssh->kex->we_need * 8);

- @@ -272,6 +276,8 @@ kexgss_client(struct ssh *ssh) {

-  	switch (ssh->kex->kex_type) {

-  	case KEX_GSS_GRP1_SHA1:

-  	case KEX_GSS_GRP14_SHA1:

- +	case KEX_GSS_GRP14_SHA256:

- +	case KEX_GSS_GRP16_SHA512:

-  		kex_dh_hash(ssh->kex->hash_alg, ssh->kex->client_version_string, 

-  		    ssh->kex->server_version_string,

- 		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),

- diff --git a/kexgsss.c b/kexgsss.c

- index 82a715cc..b7da8823 100644

- --- a/kexgsss.c

- +++ b/kexgsss.c

- @@ -104,8 +104,12 @@ kexgss_server(struct ssh *ssh)

-  		dh = dh_new_group1();

-  		break;

-  	case KEX_GSS_GRP14_SHA1:

- +	case KEX_GSS_GRP14_SHA256:

-  		dh = dh_new_group14();

-  		break;

- +	case KEX_GSS_GRP16_SHA512:

- +		dh = dh_new_group16();

- +		break;

-  	case KEX_GSS_GEX_SHA1:

-  		debug("Doing group exchange");

-  		packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);

- @@ -223,6 +227,8 @@ kexgss_server(struct ssh *ssh)

-  	switch (ssh->kex->kex_type) {

-  	case KEX_GSS_GRP1_SHA1:

-  	case KEX_GSS_GRP14_SHA1:

- +	case KEX_GSS_GRP14_SHA256:

- +	case KEX_GSS_GRP16_SHA512:

-  		kex_dh_hash(ssh->kex->hash_alg,

-  		    ssh->kex->client_version_string, ssh->kex->server_version_string,

- 		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),

- diff --git a/monitor.c b/monitor.c

- index 17046936..d6bc7ac7 100644

- --- a/monitor.c

- +++ b/monitor.c

- @@ -1648,6 +1648,8 @@ monitor_apply_keystate(struct monitor *pmonitor)

-  	if (options.gss_keyex) {

-  		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;

-  		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;

- +		kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server;

- +		kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server;

-  		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;

-  	}

-  #endif

- diff --git a/regress/kextype.sh b/regress/kextype.sh

- index 780362ca..45f4f16d 100644

- --- a/regress/kextype.sh

- +++ b/regress/kextype.sh

- @@ -14,7 +14,9 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy

-  

-  tries="1 2 3 4"

-  for k in `${SSH} -Q kex`; do

- -	if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o $k = "gss-group14-sha1-" ]; then

- +	if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o \

- +	    $k = "gss-group14-sha1-" -o $k = "gss-group14-sha256-" -o \

- +	    $k = "gss-group16-sha512-" ]; then

-  		continue

-  	fi

-  	verbose "kex $k"

- diff --git a/regress/rekey.sh b/regress/rekey.sh

- index 9fbe9b38..a2921bef 100644

- --- a/regress/rekey.sh

- +++ b/regress/rekey.sh

- @@ -38,7 +38,9 @@ increase_datafile_size 300

-  

-  opts=""

-  for i in `${SSH} -Q kex`; do

- -	if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o $i = "gss-group14-sha1-" ]; then

- +	if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o \

- +	    $i = "gss-group14-sha1-" -o $i = "gss-group14-sha256-" -o \

- +	    $i = "gss-group16-sha512-" ]; then

-  		continue

-  	fi

-  	opts="$opts KexAlgorithms=$i"

- @@ -59,7 +61,9 @@ done

-  if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then

-    for c in `${SSH} -Q cipher-auth`; do

-      for kex in `${SSH} -Q kex`; do

- -	if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o $kex = "gss-group14-sha1-" ]; then

- +	if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o \

- +	    $kex = "gss-group14-sha1-" -o $kex = "gss-group14-sha256-" -o \

- +	    $kex = "gss-group16-sha512-" ]; then

-  		continue

-  	fi

-  	verbose "client rekey $c $kex"

- diff --git a/ssh-gss.h b/ssh-gss.h

- index 6b6adb2b..7bf8d75e 100644

- --- a/ssh-gss.h

- +++ b/ssh-gss.h

- @@ -70,6 +70,8 @@

-  #define SSH2_MSG_KEXGSS_GROUP				41

-  #define KEX_GSS_GRP1_SHA1_ID				"gss-group1-sha1-"

-  #define KEX_GSS_GRP14_SHA1_ID				"gss-group14-sha1-"

- +#define KEX_GSS_GRP14_SHA256_ID			"gss-group14-sha256-"

- +#define KEX_GSS_GRP16_SHA512_ID			"gss-group16-sha512-"

-  #define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"

-  

-  #define        GSS_KEX_DEFAULT_KEX \

- diff --git a/ssh_config.5 b/ssh_config.5

- index 6b24649e..3d6da510 100644

- --- a/ssh_config.5

- +++ b/ssh_config.5

- @@ -760,7 +760,9 @@ key exchange. Possible values are

-  .Bd -literal -offset 3n

-  gss-gex-sha1-,

-  gss-group1-sha1-,

- -gss-group14-sha1-

- +gss-group14-sha1-,

- +gss-group14-sha256-,

- +gss-group16-sha512-

-  .Ed

-  .Pp

-  The default is

- diff --git a/sshconnect2.c b/sshconnect2.c

- index 8db98293..5d6b8be0 100644

- --- a/sshconnect2.c

- +++ b/sshconnect2.c

- @@ -253,6 +253,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)

-  	if (options.gss_keyex) {

-  		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;

-  		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;

- +		kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client;

- +		kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client;

-  		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;

-  	}

-  #endif

- diff --git a/sshd.c b/sshd.c

- index 895df26f..e4c879a2 100644

- --- a/sshd.c

- +++ b/sshd.c

- @@ -2244,6 +2244,8 @@ do_ssh2_kex(void)

-  	if (options.gss_keyex) {

-  		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;

-  		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;

- +		kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server;

- +		kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server;

-  		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;

-  	}

-  #endif

- diff --git a/sshd_config.5 b/sshd_config.5

- index bf81f6af..0793418b 100644

- --- a/sshd_config.5

- +++ b/sshd_config.5

- @@ -675,7 +675,9 @@ key exchange. Possible values are

-  .Bd -literal -offset 3n

-  gss-gex-sha1-,

-  gss-group1-sha1-,

- -gss-group14-sha1-

- +gss-group14-sha1-,

- +gss-group14-sha256-,

- +gss-group16-sha512-

-  .Ed

-  .Pp

-  The default is

- -- 

- 2.13.5

- 

- 

- From 7d56144903fc625c33da7fabf103f4f6bba4d43a Mon Sep 17 00:00:00 2001

- From: Jakub Jelen <jjelen@redhat.com>

- Date: Tue, 29 Aug 2017 15:32:14 +0200

- Subject: [PATCH 2/3] GSSAPI Key exchange using ECDH and SHA2

- 

- ---

-  gss-genr.c         |  10 ++

-  kex.c              |   3 +

-  kex.h              |   4 +

-  kexgssc.c          | 392 ++++++++++++++++++++++++++++++++++++++++++++++++++++-

-  kexgsss.c          | 333 +++++++++++++++++++++++++++++++++++++++++++++

-  monitor.c          |   5 +-

-  regress/kextype.sh |   1 +

-  regress/rekey.sh   |   2 +

-  ssh-gss.h          |   2 +

-  ssh_config.5       |   4 +-

-  sshconnect2.c      |   2 +

-  sshd.c             |   2 +

-  sshd_config.5      |   4 +-

-  13 files changed, 754 insertions(+), 10 deletions(-)

- 

- diff --git a/gss-genr.c b/gss-genr.c

- index c6eff3d7..22040244 100644

- --- a/gss-genr.c

- +++ b/gss-genr.c

- @@ -198,6 +198,16 @@ ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {

-  			return GSS_C_NO_OID;

-  		name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;

-  		break;

- +	case KEX_GSS_NISTP256_SHA256:

- +		if (strlen(name) < sizeof(KEX_GSS_NISTP256_SHA256_ID))

- +			return GSS_C_NO_OID;

- +		name += sizeof(KEX_GSS_NISTP256_SHA256_ID) - 1;

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		if (strlen(name) < sizeof(KEX_GSS_C25519_SHA256_ID))

- +			return GSS_C_NO_OID;

- +		name += sizeof(KEX_GSS_C25519_SHA256_ID) - 1;

- +		break;

-  	default:

-  		return GSS_C_NO_OID;

-  	}

- diff --git a/kex.c b/kex.c

- index e798fecb..bdeeada9 100644

- --- a/kex.c

- +++ b/kex.c

- @@ -114,6 +114,9 @@ static const struct kexalg kexalgs[] = {

-  	{ KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },

-  	{ KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },

-  	{ KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },

- +	{ KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256,

- +	    NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },

- +	{ KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 },

-  #endif

-  	{ NULL, -1, -1, -1},

-  };

- diff --git a/kex.h b/kex.h

- index f27958ae..7def8561 100644

- --- a/kex.h

- +++ b/kex.h

- @@ -105,6 +105,8 @@ enum kex_exchange {

-  	KEX_GSS_GRP14_SHA256,

-  	KEX_GSS_GRP16_SHA512,

-  	KEX_GSS_GEX_SHA1,

- +	KEX_GSS_NISTP256_SHA256,

- +	KEX_GSS_C25519_SHA256,

-  #endif

-  	KEX_MAX

-  };

- @@ -211,6 +213,8 @@ int	 kexecdh_server(struct ssh *);

-  int	 kexc25519_client(struct ssh *);

-  int	 kexc25519_server(struct ssh *);

-  #ifdef GSSAPI

- +int	 kexecgss_client(struct ssh *);

- +int	 kexecgss_server(struct ssh *);

-  int	 kexgss_client(struct ssh *);

-  int	 kexgss_server(struct ssh *);

-  #endif

- diff --git a/kexgssc.c b/kexgssc.c

- index ed23f06d..bdb3109a 100644

- --- a/kexgssc.c

- +++ b/kexgssc.c

- @@ -43,6 +43,7 @@

-  #include "packet.h"

-  #include "dh.h"

-  #include "digest.h"

- +#include "ssherr.h"

-  

-  #include "ssh-gss.h"

-  

- @@ -52,7 +53,7 @@ kexgss_client(struct ssh *ssh) {

-  	gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;

-  	Gssctxt *ctxt;

-  	OM_uint32 maj_status, min_status, ret_flags;

- -	u_int klen, kout, slen = 0, strlen;

- +	u_int klen, kout, slen = 0, packet_len;

-  	DH *dh; 

-  	BIGNUM *dh_server_pub = NULL;

-  	BIGNUM *shared_secret = NULL;

- @@ -201,20 +202,20 @@ kexgss_client(struct ssh *ssh) {

-  				debug("Received GSSAPI_CONTINUE");

-  				if (maj_status == GSS_S_COMPLETE) 

-  					fatal("GSSAPI Continue received from server when complete");

- -				recv_tok.value = packet_get_string(&strlen);

- -				recv_tok.length = strlen; 

- +				recv_tok.value = packet_get_string(&packet_len);

- +				recv_tok.length = packet_len;

-  				break;

-  			case SSH2_MSG_KEXGSS_COMPLETE:

-  				debug("Received GSSAPI_COMPLETE");

-  				packet_get_bignum2(dh_server_pub);

- -				msg_tok.value =  packet_get_string(&strlen);

- -				msg_tok.length = strlen; 

- +				msg_tok.value =  packet_get_string(&packet_len);

- +				msg_tok.length = packet_len;

-  

-  				/* Is there a token included? */

-  				if (packet_get_char()) {

-  					recv_tok.value=

- -					    packet_get_string(&strlen);

- -					recv_tok.length = strlen;

- +					    packet_get_string(&packet_len);

- +					recv_tok.length = packet_len;

-  					/* If we're already complete - protocol error */

-  					if (maj_status == GSS_S_COMPLETE)

-  						packet_disconnect("Protocol error: received token when complete");

- @@ -344,4 +345,382 @@ kexgss_client(struct ssh *ssh) {

-  	return kex_send_newkeys(ssh);

-  }

-  

- +int

- +kexecgss_client(struct ssh *ssh) {

- +	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;

- +	gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;

- +	Gssctxt *ctxt;

- +	OM_uint32 maj_status, min_status, ret_flags;

- +	u_int klen = 0, slen = 0, packet_len;

- +	u_char *server_pub = NULL;

- +	u_int server_pub_len = 0;

- +	BIGNUM *shared_secret = NULL;

- +	u_char *kbuf = NULL;

- +	u_char *serverhostkey = NULL;

- +	u_char *empty = "";

- +	char *msg;

- +	char *lang;

- +	int type = 0;

- +	int first = 1;

- +	u_char hash[SSH_DIGEST_MAX_LENGTH];

- +	size_t hashlen;

- +	const EC_GROUP *group = NULL;

- +	const EC_POINT *public_key;

- +	struct sshbuf *Q_C = NULL;

- +	struct kex *kex = ssh->kex;

- +	EC_POINT *server_public = NULL;

- +	struct sshbuf *c25519_shared_secret = NULL;

- +	int r;

- +

- +	/* Initialise our GSSAPI world */

- +	ssh_gssapi_build_ctx(&ctxt);

- +	if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)

- +	    == GSS_C_NO_OID)

- +		fatal("Couldn't identify host exchange");

- +

- +	if (ssh_gssapi_import_name(ctxt, kex->gss_host))

- +		fatal("Couldn't import hostname");

- +

- +	if (kex->gss_client &&

- +	    ssh_gssapi_client_identity(ctxt, kex->gss_client))

- +		fatal("Couldn't acquire client credentials");

- +

- +	if ((Q_C = sshbuf_new()) == NULL) {

- +		r = SSH_ERR_ALLOC_FAIL;

- +		goto out;

- +	}

- +

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		if ((kex->ec_client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {

- +			r = SSH_ERR_ALLOC_FAIL;

- +			goto out;

- +		}

- +		if (EC_KEY_generate_key(kex->ec_client_key) != 1) {

- +			r = SSH_ERR_LIBCRYPTO_ERROR;

- +			goto out;

- +		}

- +		group = EC_KEY_get0_group(kex->ec_client_key);

- +		public_key = EC_KEY_get0_public_key(kex->ec_client_key);

- +#ifdef DEBUG_KEXECDH

- +	fputs("client private key:\n", stderr);

- +	sshkey_dump_ec_key(kex->ec_client_key);

- +#endif

- +

- +		sshbuf_put_ec(Q_C, public_key, group);

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey);

- +#ifdef DEBUG_KEXECDH

- +		dump_digest("client private key:", kex->c25519_client_key,

- +		    sizeof(kex->c25519_client_key));

- +#endif

- +

- +		if ((r = sshbuf_put_string(Q_C, kex->c25519_client_pubkey,

- +		    sizeof(kex->c25519_client_pubkey))) != 0)

- +			fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);

- +	}

- +

- +	token_ptr = GSS_C_NO_BUFFER;

- +

- +	do {

- +		/* Step 2 - call GSS_Init_sec_context() */

- +		debug("Calling gss_init_sec_context");

- +

- +		maj_status = ssh_gssapi_init_ctx(ctxt,

- +		    kex->gss_deleg_creds, token_ptr, &send_tok,

- +		    &ret_flags);

- +

- +		if (GSS_ERROR(maj_status)) {

- +			if (send_tok.length != 0) {

- +				packet_start(SSH2_MSG_KEXGSS_CONTINUE);

- +				packet_put_string(send_tok.value,

- +				    send_tok.length);

- +			}

- +			fatal("gss_init_context failed");

- +		}

- +

- +		/* If we've got an old receive buffer get rid of it */

- +		if (token_ptr != GSS_C_NO_BUFFER)

- +			free(recv_tok.value);

- +

- +		if (maj_status == GSS_S_COMPLETE) {

- +			/* If mutual state flag is not true, kex fails */

- +			if (!(ret_flags & GSS_C_MUTUAL_FLAG))

- +				fatal("Mutual authentication failed");

- +

- +			/* If integ avail flag is not true kex fails */

- +			if (!(ret_flags & GSS_C_INTEG_FLAG))

- +				fatal("Integrity check failed");

- +		}

- +

- +		/*

- +		 * If we have data to send, then the last message that we

- +		 * received cannot have been a 'complete'.

- +		 */

- +		if (send_tok.length != 0) {

- +			if (first) {

- +				const u_char * ptr;

- +				size_t len;

- +

- +				packet_start(SSH2_MSG_KEXGSS_INIT);

- +				packet_put_string(send_tok.value,

- +				    send_tok.length);

- +				sshbuf_get_string_direct(Q_C, &ptr, &len);

- +				packet_put_string(ptr, len);

- +				first = 0;

- +			} else {

- +				packet_start(SSH2_MSG_KEXGSS_CONTINUE);

- +				packet_put_string(send_tok.value,

- +				    send_tok.length);

- +			}

- +			packet_send();

- +			gss_release_buffer(&min_status, &send_tok);

- +

- +			/* If we've sent them data, they should reply */

- +			do {

- +				type = packet_read();

- +				if (type == SSH2_MSG_KEXGSS_HOSTKEY) {

- +					debug("Received KEXGSS_HOSTKEY");

- +					if (serverhostkey)

- +						fatal("Server host key received more than once");

- +					serverhostkey =

- +					    packet_get_string(&slen);

- +				}

- +			} while (type == SSH2_MSG_KEXGSS_HOSTKEY);

- +

- +			switch (type) {

- +			case SSH2_MSG_KEXGSS_CONTINUE:

- +				debug("Received GSSAPI_CONTINUE");

- +				if (maj_status == GSS_S_COMPLETE)

- +					fatal("GSSAPI Continue received from server when complete");

- +				recv_tok.value = packet_get_string(&packet_len);

- +				recv_tok.length = packet_len;

- +				break;

- +			case SSH2_MSG_KEXGSS_COMPLETE:

- +				debug("Received GSSAPI_COMPLETE");

- +				server_pub = packet_get_string(&server_pub_len);

- +				msg_tok.value = packet_get_string(&packet_len);

- +				msg_tok.length = packet_len;

- +

- +				/* Is there a token included? */

- +				if (packet_get_char()) {

- +					recv_tok.value=

- +					    packet_get_string(&packet_len);

- +					recv_tok.length = packet_len;

- +					/* If we're already complete - protocol error */

- +					if (maj_status == GSS_S_COMPLETE)

- +						packet_disconnect("Protocol error: received token when complete");

- +					} else {

- +						/* No token included */

- +						if (maj_status != GSS_S_COMPLETE)

- +							packet_disconnect("Protocol error: did not receive final token");

- +				}

- +				break;

- +			case SSH2_MSG_KEXGSS_ERROR:

- +				debug("Received Error");

- +				maj_status = packet_get_int();

- +				min_status = packet_get_int();

- +				msg = packet_get_string(NULL);

- +				lang = packet_get_string(NULL);

- +				fatal("GSSAPI Error: \n%.400s",msg);

- +			default:

- +				packet_disconnect("Protocol error: didn't expect packet type %d",

- +				    type);

- +			}

- +			token_ptr = &recv_tok;

- +		} else {

- +			/* No data, and not complete */

- +			if (maj_status != GSS_S_COMPLETE)

- +				fatal("Not complete, and no token output");

- +		}

- +	} while (maj_status & GSS_S_CONTINUE_NEEDED);

- +

- +	/*

- +	 * We _must_ have received a COMPLETE message in reply from the

- +	 * server, which will have set dh_server_pub and msg_tok

- +	 */

- +

- +	if (type != SSH2_MSG_KEXGSS_COMPLETE)

- +		fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");

- +

- +	/* 7. C verifies that the key Q_S is valid */

- +	/* 8. C computes shared secret */

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		if (server_pub_len != 65)

- +			fatal("The received NIST-P256 key did not match"

- +			    "expected length (expected 65, got %d)", server_pub_len);

- +

- +		if (server_pub[0] != POINT_CONVERSION_UNCOMPRESSED)

- +			fatal("The received NIST-P256 key does not have first octet 0x04");

- +

- +		if ((server_public = EC_POINT_new(group)) == NULL) {

- +			r = SSH_ERR_ALLOC_FAIL;

- +			goto out;

- +		}

- +

- +		if (!EC_POINT_oct2point(group, server_public, server_pub,

- +		    server_pub_len, NULL))

- +			fatal("Can not decode received NIST-P256 client key");

- +#ifdef DEBUG_KEXECDH

- +		fputs("server public key:\n", stderr);

- +		sshkey_dump_ec_point(group, server_public);

- +#endif

- +

- +		if (sshkey_ec_validate_public(group, server_public) != 0) {

- +			sshpkt_disconnect(ssh, "invalid client public key");

- +			r = SSH_ERR_MESSAGE_INCOMPLETE;

- +			goto out;

- +		}

- +

- +		if (!EC_POINT_is_on_curve(group, server_public, NULL))

- +			fatal("Received NIST-P256 client key is not on curve");

- +

- +		/* Calculate shared_secret */

- +		klen = (EC_GROUP_get_degree(group) + 7) / 8;

- +		if ((kbuf = malloc(klen)) == NULL ||

- +		    (shared_secret = BN_new()) == NULL) {

- +			r = SSH_ERR_ALLOC_FAIL;

- +			goto out;

- +		}

- +		if (ECDH_compute_key(kbuf, klen, server_public,

- +		    kex->ec_client_key, NULL) != (int)klen ||

- +		    BN_bin2bn(kbuf, klen, shared_secret) == NULL) {

- +			r = SSH_ERR_LIBCRYPTO_ERROR;

- +			goto out;

- +		}

- +#ifdef DEBUG_KEXECDH

- +		dump_digest("shared secret", kbuf, klen);

- +#endif

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		if (server_pub_len != 32)

- +			fatal("The received curve25519 key did not match"

- +			    "expected length (expected 32, got %d)", server_pub_len);

- +

- +		if (server_pub[server_pub_len-1] & 0x80)

- +			fatal("The received key has MSB of last octet set!");

- +#ifdef DEBUG_KEXECDH

- +		dump_digest("server public key:", server_pub, CURVE25519_SIZE);

- +#endif

- +

- +		/* generate shared secret */

- +		if ((c25519_shared_secret = sshbuf_new()) == NULL) {

- +			r = SSH_ERR_ALLOC_FAIL;

- +			goto out;

- +		}

- +		if ((r = kexc25519_shared_key(kex->c25519_client_key,

- +		    server_pub, c25519_shared_secret)) < 0)

- +			goto out;

- +

- +		/* if all octets of the shared secret are zero octets,

- +		 * is already checked in kexc25519_shared_key() */

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);

- +	}

- +

- +	hashlen = sizeof(hash);

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		kex_ecdh_hash(

- +		    kex->hash_alg,

- +		    group,

- +		    kex->client_version_string,

- +		    kex->server_version_string,

- +		    sshbuf_ptr(kex->my), sshbuf_len(kex->my),

- +		    sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),

- +		    (serverhostkey ? serverhostkey : empty), slen,

- +		    EC_KEY_get0_public_key(kex->ec_client_key),

- +		    server_public,

- +		    shared_secret,

- +		    hash, &hashlen

- +		);

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		kex_c25519_hash(

- +		    kex->hash_alg,

- +		    kex->client_version_string, kex->server_version_string,

- +		    sshbuf_ptr(kex->my), sshbuf_len(kex->my),

- +		    sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),

- +		    (serverhostkey ? serverhostkey : empty), slen,

- +		    kex->c25519_client_pubkey, server_pub,

- +		    sshbuf_ptr(c25519_shared_secret), sshbuf_len(c25519_shared_secret),

- +		    hash, &hashlen

- +		);

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);

- +	}

- +

- +	gssbuf.value = hash;

- +	gssbuf.length = hashlen;

- +

- +	/* Verify that the hash matches the MIC we just got. */

- +	if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))

- +		packet_disconnect("Hash's MIC didn't verify");

- +

- +	free(msg_tok.value);

- +

- +	/* save session id */

- +	if (kex->session_id == NULL) {

- +		kex->session_id_len = hashlen;

- +		kex->session_id = xmalloc(kex->session_id_len);

- +		memcpy(kex->session_id, hash, kex->session_id_len);

- +	}

- +

- +	if (kex->gss_deleg_creds)

- +		ssh_gssapi_credentials_updated(ctxt);

- +

- +	if (gss_kex_context == NULL)

- +		gss_kex_context = ctxt;

- +	else

- +		ssh_gssapi_delete_ctx(&ctxt);

- +

- +	/* Finally derive the keys and send them */

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) != 0)

- +			goto out;

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		if ((r = kex_derive_keys(ssh, hash, hashlen, c25519_shared_secret)) != 0)

- +			goto out;

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);

- +	}

- +	r = kex_send_newkeys(ssh);

- +out:

- +	free(serverhostkey);

- +	explicit_bzero(hash, sizeof(hash));

- +	sshbuf_free(Q_C);

- +	if (server_pub)

- +		free(server_pub);

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		if (kex->ec_client_key) {

- +			EC_KEY_free(kex->ec_client_key);

- +			kex->ec_client_key = NULL;

- +		}

- +		if (server_public)

- +			EC_POINT_clear_free(server_public);

- +		if (kbuf) {

- +			explicit_bzero(kbuf, klen);

- +			free(kbuf);

- +		}

- +		if (shared_secret)

- +			BN_clear_free(shared_secret);

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));

- +		sshbuf_free(c25519_shared_secret);

- +		break;

- +	}

- +	return r;

- +}

-  #endif /* GSSAPI */

- diff --git a/kexgsss.c b/kexgsss.c

- index b7da8823..a7c42803 100644

- --- a/kexgsss.c

- +++ b/kexgsss.c

- @@ -46,6 +46,7 @@

-  #include "servconf.h"

-  #include "ssh-gss.h"

-  #include "digest.h"

- +#include "ssherr.h"

-  

-  extern ServerOptions options;

-  

- @@ -303,4 +304,338 @@ kexgss_server(struct ssh *ssh)

-  		ssh_gssapi_rekey_creds();

-  	return 0;

-  }

- +

- +int

- +kexecgss_server(struct ssh *ssh)

- +{

- +	OM_uint32 maj_status, min_status;

- +

- +	/*

- +	 * Some GSSAPI implementations use the input value of ret_flags (an

- +	 * output variable) as a means of triggering mechanism specific

- +	 * features. Initializing it to zero avoids inadvertently

- +	 * activating this non-standard behaviour.

- +	 */

- +

- +	OM_uint32 ret_flags = 0;

- +	gss_buffer_desc gssbuf, recv_tok, msg_tok;

- +	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;

- +	Gssctxt *ctxt = NULL;

- +	u_int slen, klen = 0;

- +	u_char *kbuf = NULL;

- +	BIGNUM *shared_secret = NULL;

- +	int type = 0;

- +	gss_OID oid;

- +	char *mechs;

- +	u_char hash[SSH_DIGEST_MAX_LENGTH];

- +	size_t hashlen;

- +	u_char *client_pub = NULL;

- +	u_int client_pub_len = 0;

- +	const EC_GROUP *group = NULL;

- +	EC_POINT *client_public = NULL;

- +	EC_KEY *server_key = NULL;

- +	const EC_POINT *public_key;

- +	u_char c25519_server_key[CURVE25519_SIZE];

- +	u_char c25519_server_pubkey[CURVE25519_SIZE];

- +	struct sshbuf *c25519_shared_secret = NULL;

- +	struct sshbuf *Q_S;

- +	struct kex *kex = ssh->kex;

- +	int r;

- +

- +	/* Initialise GSSAPI */

- +

- +	/* If we're rekeying, privsep means that some of the private structures

- +	 * in the GSSAPI code are no longer available. This kludges them back

- +	 * into life

- +	 */

- +	if (!ssh_gssapi_oid_table_ok())

- +		if ((mechs = ssh_gssapi_server_mechanisms()))

- +			free(mechs);

- +

- +	debug2("%s: Identifying %s", __func__, kex->name);

- +	oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);

- +	if (oid == GSS_C_NO_OID)

- +	   fatal("Unknown gssapi mechanism");

- +

- +	debug2("%s: Acquiring credentials", __func__);

- +

- +	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))

- +		fatal("Unable to acquire credentials for the server");

- +

- +	if ((Q_S = sshbuf_new()) == NULL) {

- +		r = SSH_ERR_ALLOC_FAIL;

- +		goto out;

- +	}

- +

- +	/* 5. S generates an ephemeral key pair (do the allocations early) */

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {

- +			r = SSH_ERR_ALLOC_FAIL;

- +			goto out;

- +		}

- +		if (EC_KEY_generate_key(server_key) != 1) {

- +			r = SSH_ERR_LIBCRYPTO_ERROR;

- +			goto out;

- +		}

- +		group = EC_KEY_get0_group(server_key);

- +		public_key = EC_KEY_get0_public_key(server_key);

- +

- +		sshbuf_put_ec(Q_S, public_key, group);

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		kexc25519_keygen(c25519_server_key, c25519_server_pubkey);

- +#ifdef DEBUG_KEXECDH

- +		dump_digest("server private key:", c25519_server_key,

- +		    sizeof(c25519_server_key));

- +#endif

- +		if ((r = sshbuf_put_string(Q_S, c25519_server_pubkey,

- +		    sizeof(c25519_server_pubkey))) != 0)

- +			fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);

- +	}

- +

- +	do {

- +		debug("Wait SSH2_MSG_GSSAPI_INIT");

- +		type = packet_read();

- +		switch(type) {

- +		case SSH2_MSG_KEXGSS_INIT:

- +			if (client_pub != NULL)

- +				fatal("Received KEXGSS_INIT after initialising");

- +			recv_tok.value = packet_get_string(&slen);

- +			recv_tok.length = slen;

- +

- +			client_pub = packet_get_string(&client_pub_len);

- +

- +			/* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */

- +			break;

- +		case SSH2_MSG_KEXGSS_CONTINUE:

- +			recv_tok.value = packet_get_string(&slen);

- +			recv_tok.length = slen;

- +			break;

- +		default:

- +			packet_disconnect(

- +			    "Protocol error: didn't expect packet type %d",

- +			    type);

- +		}

- +

- +		maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok,

- +		    &send_tok, &ret_flags));

- +

- +		free(recv_tok.value);

- +

- +		if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)

- +			fatal("Zero length token output when incomplete");

- +

- +		if (client_pub == NULL)

- +			fatal("No client public key");

- +

- +		if (maj_status & GSS_S_CONTINUE_NEEDED) {

- +			debug("Sending GSSAPI_CONTINUE");

- +			packet_start(SSH2_MSG_KEXGSS_CONTINUE);

- +			packet_put_string(send_tok.value, send_tok.length);

- +			packet_send();

- +			gss_release_buffer(&min_status, &send_tok);

- +		}

- +	} while (maj_status & GSS_S_CONTINUE_NEEDED);

- +

- +	if (GSS_ERROR(maj_status)) {

- +		if (send_tok.length > 0) {

- +			packet_start(SSH2_MSG_KEXGSS_CONTINUE);

- +			packet_put_string(send_tok.value, send_tok.length);

- +			packet_send();

- +		}

- +		fatal("accept_ctx died");

- +	}

- +

- +	if (!(ret_flags & GSS_C_MUTUAL_FLAG))

- +		fatal("Mutual Authentication flag wasn't set");

- +

- +	if (!(ret_flags & GSS_C_INTEG_FLAG))

- +		fatal("Integrity flag wasn't set");

- +

- +	/* 3. S verifies that the (client) key is valid */

- +	/* calculate shared secret */

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		if (client_pub_len != 65)

- +			fatal("The received NIST-P256 key did not match"

- +			    "expected length (expected 65, got %d)", client_pub_len);

- +

- +		if (client_pub[0] != POINT_CONVERSION_UNCOMPRESSED)

- +			fatal("The received NIST-P256 key does not have first octet 0x04");

- +

- +		if ((client_public = EC_POINT_new(group)) == NULL) {

- +			r = SSH_ERR_ALLOC_FAIL;

- +			goto out;

- +		}

- +

- +		if (!EC_POINT_oct2point(group, client_public, client_pub,

- +		    client_pub_len, NULL))

- +			fatal("Can not decode received NIST-P256 client key");

- +

- +		if (sshkey_ec_validate_public(group, client_public) != 0) {

- +			sshpkt_disconnect(ssh, "invalid client public key");

- +			r = SSH_ERR_MESSAGE_INCOMPLETE;

- +			goto out;

- +		}

- +

- +		if (!EC_POINT_is_on_curve(group, client_public, NULL))

- +			fatal("Received NIST-P256 client key is not on curve");

- +

- +		/* Calculate shared_secret */

- +		klen = (EC_GROUP_get_degree(group) + 7) / 8;

- +		if ((kbuf = malloc(klen)) == NULL ||

- +		    (shared_secret = BN_new()) == NULL) {

- +			r = SSH_ERR_ALLOC_FAIL;

- +			goto out;

- +		}

- +		if (ECDH_compute_key(kbuf, klen, client_public,

- +		    server_key, NULL) != (int)klen ||

- +		    BN_bin2bn(kbuf, klen, shared_secret) == NULL) {

- +			r = SSH_ERR_LIBCRYPTO_ERROR;

- +			goto out;

- +		}

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		if (client_pub_len != 32)

- +			fatal("The received curve25519 key did not match"

- +			    "expected length (expected 32, got %d)", client_pub_len);

- +

- +		if (client_pub[client_pub_len-1] & 0x80)

- +			fatal("The received key has MSB of last octet set!");

- +

- +		/* generate shared secret */

- +		if ((c25519_shared_secret = sshbuf_new()) == NULL) {

- +			r = SSH_ERR_ALLOC_FAIL;

- +			goto out;

- +		}

- +		if ((r = kexc25519_shared_key(c25519_server_key,

- +		    client_pub, c25519_shared_secret)) < 0)

- +			goto out;

- +

- +		/* if all octets of the shared secret are zero octets,

- +		 * is already checked in kexc25519_shared_key() */

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);

- +	}

- +

- +	hashlen = sizeof(hash);

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		kex_ecdh_hash(

- +		    kex->hash_alg,

- +		    group,

- +		    kex->client_version_string,

- +		    kex->server_version_string,

- +		    sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),

- +		    sshbuf_ptr(kex->my), sshbuf_len(kex->my),

- +		    NULL, 0,

- +		    client_public,

- +		    EC_KEY_get0_public_key(server_key),

- +		    shared_secret,

- +		    hash, &hashlen

- +		);

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		kex_c25519_hash(

- +		    kex->hash_alg,

- +		    kex->client_version_string, kex->server_version_string,

- +		    sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),

- +		    sshbuf_ptr(kex->my), sshbuf_len(kex->my),

- +		    NULL, 0,

- +		    client_pub, c25519_server_pubkey,

- +		    sshbuf_ptr(c25519_shared_secret), sshbuf_len(c25519_shared_secret),

- +		    hash, &hashlen

- +		);

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);

- +	}

- +

- +	if (kex->session_id == NULL) {

- +		kex->session_id_len = hashlen;

- +		kex->session_id = xmalloc(kex->session_id_len);

- +		memcpy(kex->session_id, hash, kex->session_id_len);

- +	}

- +

- +	gssbuf.value = hash;

- +	gssbuf.length = hashlen;

- +

- +	if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))

- +		fatal("Couldn't get MIC");

- +

- +	packet_start(SSH2_MSG_KEXGSS_COMPLETE);

- +	{

- +		const u_char *ptr;

- +		size_t len;

- +		if ((r = sshbuf_get_string_direct(Q_S, &ptr, &len)) != 0)

- +			fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +		packet_put_string(ptr, len);

- +	}

- +	packet_put_string(msg_tok.value, msg_tok.length);

- +

- +	if (send_tok.length != 0) {

- +		packet_put_char(1); /* true */

- +		packet_put_string(send_tok.value, send_tok.length);

- +	} else {

- +		packet_put_char(0); /* false */

- +	}

- +	packet_send();

- +

- +	gss_release_buffer(&min_status, &send_tok);

- +	gss_release_buffer(&min_status, &msg_tok);

- +

- +	if (gss_kex_context == NULL)

- +		gss_kex_context = ctxt;

- +	else

- +		ssh_gssapi_delete_ctx(&ctxt);

- +

- +	/* Finally derive the keys and send them */

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) != 0)

- +			goto out;

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		if ((r = kex_derive_keys(ssh, hash, hashlen, c25519_shared_secret)) != 0)

- +			goto out;

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);

- +	}

- +	if ((r = kex_send_newkeys(ssh)) != 0)

- +		goto out;

- +

- +	/* If this was a rekey, then save out any delegated credentials we

- +	 * just exchanged.  */

- +	if (options.gss_store_rekey)

- +		ssh_gssapi_rekey_creds();

- +out:

- +	explicit_bzero(hash, sizeof(hash));

- +	if (Q_S)

- +		sshbuf_free(Q_S);

- +	if (client_pub)

- +		free(client_pub);

- +	switch (kex->kex_type) {

- +	case KEX_GSS_NISTP256_SHA256:

- +		if (server_key)

- +			EC_KEY_free(server_key);

- +		if (kbuf) {

- +			explicit_bzero(kbuf, klen);

- +			free(kbuf);

- +		}

- +		if (shared_secret)

- +			BN_clear_free(shared_secret);

- +		break;

- +	case KEX_GSS_C25519_SHA256:

- +		explicit_bzero(c25519_server_key, sizeof(c25519_server_key));

- +		sshbuf_free(c25519_shared_secret);

- +		break;

- +	}

- +	return r;

- +}

-  #endif /* GSSAPI */

- diff --git a/monitor.c b/monitor.c

- index d6bc7ac7..b11616c8 100644

- --- a/monitor.c

- +++ b/monitor.c

- @@ -1651,6 +1651,8 @@ monitor_apply_keystate(struct monitor *pmonitor)

-  		kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server;

-  		kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server;

-  		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;

- +		kex->kex[KEX_GSS_NISTP256_SHA256] = kexecgss_server;

- +		kex->kex[KEX_GSS_C25519_SHA256] = kexecgss_server;

-  	}

-  #endif

-  		kex->load_host_public_key=&get_hostkey_public_by_type;

- @@ -1867,7 +1869,8 @@ mm_answer_gss_sign(int socket, Buffer *m)

-  

-  	if ((r = sshbuf_get_string(m, (u_char **)&data.value, &data.length)) != 0)

-  		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- -	if (data.length != 20) 

- +	/* Lengths of SHA-1, SHA-256 and SHA-512 hashes that are used */

- +	if (data.length != 20 && data.length != 32 && data.length != 64)

-  		fatal("%s: data length incorrect: %d", __func__, 

-  		    (int) data.length);

-  

- diff --git a/regress/kextype.sh b/regress/kextype.sh

- index 45f4f16d..d5b4a713 100644

- --- a/regress/kextype.sh

- +++ b/regress/kextype.sh

- @@ -15,6 +15,7 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy

-  tries="1 2 3 4"

-  for k in `${SSH} -Q kex`; do

-  	if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o \

- +	    $k = "gss-nistp256-sha256-" -o $k = "gss-curve25519-sha256-" -o \

-  	    $k = "gss-group14-sha1-" -o $k = "gss-group14-sha256-" -o \

-  	    $k = "gss-group16-sha512-" ]; then

-  		continue

- diff --git a/regress/rekey.sh b/regress/rekey.sh

- index a2921bef..b118c6c8 100644

- --- a/regress/rekey.sh

- +++ b/regress/rekey.sh

- @@ -39,6 +39,7 @@ increase_datafile_size 300

-  opts=""

-  for i in `${SSH} -Q kex`; do

-  	if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o \

- +	    $i = "gss-nistp256-sha256-" -o $i = "gss-curve25519-sha256-" -o \

-  	    $i = "gss-group14-sha1-" -o $i = "gss-group14-sha256-" -o \

-  	    $i = "gss-group16-sha512-" ]; then

-  		continue

- @@ -62,6 +63,7 @@ if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then

-    for c in `${SSH} -Q cipher-auth`; do

-      for kex in `${SSH} -Q kex`; do

-  	if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o \

- +	    $kex = "gss-nistp256-sha256-" -o $kex = "gss-curve25519-sha256-" -o \

-  	    $kex = "gss-group14-sha1-" -o $kex = "gss-group14-sha256-" -o \

-  	    $kex = "gss-group16-sha512-" ]; then

-  		continue

- diff --git a/ssh-gss.h b/ssh-gss.h

- index 7bf8d75e..1f73721d 100644

- --- a/ssh-gss.h

- +++ b/ssh-gss.h

- @@ -73,6 +73,8 @@

-  #define KEX_GSS_GRP14_SHA256_ID			"gss-group14-sha256-"

-  #define KEX_GSS_GRP16_SHA512_ID			"gss-group16-sha512-"

-  #define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"

- +#define KEX_GSS_NISTP256_SHA256_ID			"gss-nistp256-sha256-"

- +#define KEX_GSS_C25519_SHA256_ID			"gss-curve25519-sha256-"

-  

-  #define        GSS_KEX_DEFAULT_KEX \

-  	KEX_GSS_GEX_SHA1_ID "," \

- diff --git a/ssh_config.5 b/ssh_config.5

- index 3d6da510..1dc29bf1 100644

- --- a/ssh_config.5

- +++ b/ssh_config.5

- @@ -762,7 +762,9 @@ gss-gex-sha1-,

-  gss-group1-sha1-,

-  gss-group14-sha1-,

-  gss-group14-sha256-,

- -gss-group16-sha512-

- +gss-group16-sha512-,

- +gss-nistp256-sha256-,

- +gss-curve25519-sha256-

-  .Ed

-  .Pp

-  The default is

- diff --git a/sshconnect2.c b/sshconnect2.c

- index 5d6b8be0..280ae5a6 100644

- --- a/sshconnect2.c

- +++ b/sshconnect2.c

- @@ -256,6 +256,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)

-  		kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client;

-  		kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client;

-  		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;

- +		kex->kex[KEX_GSS_NISTP256_SHA256] = kexecgss_client;

- +		kex->kex[KEX_GSS_C25519_SHA256] = kexecgss_client;

-  	}

-  #endif

-  	kex->kex[KEX_C25519_SHA256] = kexc25519_client;

- diff --git a/sshd.c b/sshd.c

- index e4c879a2..a35735d8 100644

- --- a/sshd.c

- +++ b/sshd.c

- @@ -2247,6 +2247,8 @@ do_ssh2_kex(void)

-  		kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server;

-  		kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server;

-  		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;

- +		kex->kex[KEX_GSS_NISTP256_SHA256] = kexecgss_server;

- +		kex->kex[KEX_GSS_C25519_SHA256] = kexecgss_server;

-  	}

-  #endif

-  	kex->server = 1;

- diff --git a/sshd_config.5 b/sshd_config.5

- index 0793418b..888316bf 100644

- --- a/sshd_config.5

- +++ b/sshd_config.5

- @@ -677,7 +677,9 @@ gss-gex-sha1-,

-  gss-group1-sha1-,

-  gss-group14-sha1-,

-  gss-group14-sha256-,

- -gss-group16-sha512-

- +gss-group16-sha512-,

- +gss-nistp256-sha256-,

- +gss-curve25519-sha256-

-  .Ed

-  .Pp

-  The default is

- -- 

- 2.13.5

- 

- 

- From 0431695660d5eb1dd1169d42a1624c75a92aa5d2 Mon Sep 17 00:00:00 2001

- From: Jakub Jelen <jjelen@redhat.com>

- Date: Wed, 30 Aug 2017 15:30:51 +0200

- Subject: [PATCH 3/3] Simplify rough edges of GSSAPI Kex

- 

- ---

-  gss-genr.c         | 53 +++++++++++++++++------------------------------------

-  regress/kextype.sh | 10 ++++------

-  regress/rekey.sh   | 20 ++++++++------------

-  3 files changed, 29 insertions(+), 54 deletions(-)

- 

- diff --git a/gss-genr.c b/gss-genr.c

- index 22040244..c671be31 100644

- --- a/gss-genr.c

- +++ b/gss-genr.c

- @@ -171,47 +171,28 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,

-  gss_OID

-  ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {

-  	int i = 0;

- -	

- -	switch (kex_type) {

- -	case KEX_GSS_GRP1_SHA1:

- -		if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))

- -			return GSS_C_NO_OID;

- -		name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;

- -		break;

- -	case KEX_GSS_GRP14_SHA1:

- -		if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))

- -			return GSS_C_NO_OID;

- -		name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;

- -		break;

- -	case KEX_GSS_GRP14_SHA256:

- -		if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA256_ID))

- -			return GSS_C_NO_OID;

- -		name += sizeof(KEX_GSS_GRP14_SHA256_ID) - 1;

- -		break;

- -	case KEX_GSS_GRP16_SHA512:

- -		if (strlen(name) < sizeof(KEX_GSS_GRP16_SHA512_ID))

- -			return GSS_C_NO_OID;

- -		name += sizeof(KEX_GSS_GRP16_SHA512_ID) - 1;

- -		break;

- -	case KEX_GSS_GEX_SHA1:

- -		if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))

- -			return GSS_C_NO_OID;

- -		name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;

- -		break;

- -	case KEX_GSS_NISTP256_SHA256:

- -		if (strlen(name) < sizeof(KEX_GSS_NISTP256_SHA256_ID))

- -			return GSS_C_NO_OID;

- -		name += sizeof(KEX_GSS_NISTP256_SHA256_ID) - 1;

- -		break;

- -	case KEX_GSS_C25519_SHA256:

- -		if (strlen(name) < sizeof(KEX_GSS_C25519_SHA256_ID))

- -			return GSS_C_NO_OID;

- -		name += sizeof(KEX_GSS_C25519_SHA256_ID) - 1;

- +

- +#define SKIP_KEX_NAME(type) \

- +	case type: \

- +		if (strlen(name) < sizeof(type##_ID)) \

- +			return GSS_C_NO_OID; \

- +		name += sizeof(type##_ID) - 1; \

-  		break;

- +

- +	switch (kex_type) {

- +	SKIP_KEX_NAME(KEX_GSS_GRP1_SHA1)

- +	SKIP_KEX_NAME(KEX_GSS_GRP14_SHA1)

- +	SKIP_KEX_NAME(KEX_GSS_GRP14_SHA256)

- +	SKIP_KEX_NAME(KEX_GSS_GRP16_SHA512)

- +	SKIP_KEX_NAME(KEX_GSS_GEX_SHA1)

- +	SKIP_KEX_NAME(KEX_GSS_NISTP256_SHA256)

- +	SKIP_KEX_NAME(KEX_GSS_C25519_SHA256)

-  	default:

-  		return GSS_C_NO_OID;

-  	}

-  

- +#undef SKIP_KEX_NAME

- +

-  	while (gss_enc2oid[i].encoded != NULL &&

-  	    strcmp(name, gss_enc2oid[i].encoded) != 0)

-  		i++;

- diff --git a/regress/kextype.sh b/regress/kextype.sh

- index d5b4a713..6b4af28a 100644

- --- a/regress/kextype.sh

- +++ b/regress/kextype.sh

- @@ -14,12 +14,10 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy

-  

-  tries="1 2 3 4"

-  for k in `${SSH} -Q kex`; do

- -	if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o \

- -	    $k = "gss-nistp256-sha256-" -o $k = "gss-curve25519-sha256-" -o \

- -	    $k = "gss-group14-sha1-" -o $k = "gss-group14-sha256-" -o \

- -	    $k = "gss-group16-sha512-" ]; then

- -		continue

- -	fi

- +	# ignore GSSAPI key exchange mechanisms (all of them start with gss-)

- +	case $k in

- +		gss-* ) continue ;;

- +	esac

-  	verbose "kex $k"

-  	for i in $tries; do

-  		${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true

- diff --git a/regress/rekey.sh b/regress/rekey.sh

- index b118c6c8..d6a8742f 100644

- --- a/regress/rekey.sh

- +++ b/regress/rekey.sh

- @@ -38,12 +38,10 @@ increase_datafile_size 300

-  

-  opts=""

-  for i in `${SSH} -Q kex`; do

- -	if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o \

- -	    $i = "gss-nistp256-sha256-" -o $i = "gss-curve25519-sha256-" -o \

- -	    $i = "gss-group14-sha1-" -o $i = "gss-group14-sha256-" -o \

- -	    $i = "gss-group16-sha512-" ]; then

- -		continue

- -	fi

- +	# ignore GSSAPI key exchange mechanisms (all of them start with gss-)

- +	case $i in

- +		gss-* ) continue ;;

- +	esac

-  	opts="$opts KexAlgorithms=$i"

-  done

-  for i in `${SSH} -Q cipher`; do

- @@ -62,12 +60,10 @@ done

-  if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then

-    for c in `${SSH} -Q cipher-auth`; do

-      for kex in `${SSH} -Q kex`; do

- -	if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o \

- -	    $kex = "gss-nistp256-sha256-" -o $kex = "gss-curve25519-sha256-" -o \

- -	    $kex = "gss-group14-sha1-" -o $kex = "gss-group14-sha256-" -o \

- -	    $kex = "gss-group16-sha512-" ]; then

- -		continue

- -	fi

- +	# ignore GSSAPI key exchange mechanisms (all of them start with gss-)

- +	case $kex in

- +		gss-* ) continue ;;

- +	esac

-  	verbose "client rekey $c $kex"

-  	ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c

-      done

- -- 

- 2.13.5

- 

file modified
+533 -393
@@ -1,83 +1,80 @@ 

- diff -up openssh-7.6p1/audit-bsm.c.audit openssh-7.6p1/audit-bsm.c

- --- openssh-7.6p1/audit-bsm.c.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/audit-bsm.c	2017-10-04 17:18:32.834505048 +0200

- @@ -373,10 +373,23 @@ audit_connection_from(const char *host,

+ diff -up openssh/audit-bsm.c.audit openssh/audit-bsm.c

+ --- openssh/audit-bsm.c.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/audit-bsm.c	2019-04-03 17:02:20.713886041 +0200

+ @@ -372,13 +372,26 @@ audit_connection_from(const char *host,

   #endif

   }

   

- -void

  +int

-  audit_run_command(const char *command)

-  {

-  	/* not implemented */

- +	return 0;

- +}

- +

- +void

- +audit_end_command(int handle, const char *command)

+ +audit_run_command(struct ssh *ssh, const char *command)

  +{

  +	/* not implemented */

+ +	return 0;

  +}

  +

- +void

- +audit_count_session_open(void)

- +{

- +	/* not necessary */

+  void

+ -audit_run_command(const char *command)

+ +audit_end_command(struct ssh *ssh, int handle, const char *command)

+  {

+  	/* not implemented */

   }

   

   void

- @@ -391,6 +404,12 @@ audit_session_close(struct logininfo *li

+ +audit_count_session_open(void)

+ +{

+ +	/* not necessary */

+ +}

+ +

+ +void

+  audit_session_open(struct logininfo *li)

+  {

+  	/* not implemented */

+ @@ -390,6 +403,12 @@ audit_session_close(struct logininfo *li

   	/* not implemented */

   }

   

  +int

- +audit_keyusage(int host_user, char *fp, int rv)

+ +audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)

  +{

  +	/* not implemented */

  +}

  +

   void

-  audit_event(ssh_audit_event_t event)

+  audit_event(struct ssh *ssh, ssh_audit_event_t event)

   {

- @@ -452,4 +471,34 @@ audit_event(ssh_audit_event_t event)

+ @@ -451,4 +470,28 @@ audit_event(struct ssh *ssh, ssh_audit_e

   		debug("%s: unhandled event %d", __func__, event);

   	}

   }

  +

  +void

- +audit_unsupported_body(int what)

+ +audit_unsupported_body(struct ssh *ssh, int what)

  +{

  +	/* not implemented */

  +}

  +

  +void

- +audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, uid_t uid)

+ +audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, uid_t uid)

  +{

  +	/* not implemented */

  +}

  +

  +void

- +audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)

+ +audit_session_key_free_body(struct ssh * ssh, int ctos, pid_t pid, uid_t uid)

  +{

  +	/* not implemented */

  +}

  +

  +void

- +audit_destroy_sensitive_data(const char *fp)

- +{

- +	/* not implemented */

- +}

- +

- +void

- +audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)

+ +audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid)

  +{

  +	/* not implemented */

  +}

   #endif /* BSM */

- diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c

- --- openssh-7.6p1/audit.c.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/audit.c	2017-10-04 17:18:32.834505048 +0200

- @@ -34,6 +35,12 @@

+ diff -up openssh/audit.c.audit openssh/audit.c

+ --- openssh/audit.c.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/audit.c	2019-04-03 17:02:20.713886041 +0200

+ @@ -34,6 +34,12 @@

   #include "log.h"

   #include "hostfile.h"

   #include "auth.h"
@@ -119,38 +116,38 @@ 

   }

   

  +void

- +audit_key(int host_user, int *rv, const struct sshkey *key)

+ +audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key)

  +{

  +	char *fp;

  +

  +	fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX);

- +	if (audit_keyusage(host_user, fp, (*rv == 0)) == 0)

+ +	if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0)

  +		*rv = -SSH_ERR_INTERNAL_ERROR;

  +	free(fp);

  +}

  +

  +void

- +audit_unsupported(int what)

+ +audit_unsupported(struct ssh *ssh, int what)

  +{

- +	PRIVSEP(audit_unsupported_body(what));

+ +	PRIVSEP(audit_unsupported_body(ssh, what));

  +}

  +

  +void

- +audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs)

+ +audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs)

  +{

- +	PRIVSEP(audit_kex_body(ctos, enc, mac, comp, pfs, getpid(), getuid()));

+ +	PRIVSEP(audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid()));

  +}

  +

  +void

- +audit_session_key_free(int ctos)

+ +audit_session_key_free(struct ssh *ssh, int ctos)

  +{

- +	PRIVSEP(audit_session_key_free_body(ctos, getpid(), getuid()));

+ +	PRIVSEP(audit_session_key_free_body(ssh, ctos, getpid(), getuid()));

  +}

  +

   # ifndef CUSTOM_SSH_AUDIT_EVENTS

   /*

    * Null implementations of audit functions.

- @@ -138,6 +173,17 @@ audit_event(ssh_audit_event_t event)

+ @@ -138,6 +171,17 @@ audit_event(struct ssh *ssh, ssh_audit_e

   }

   

   /*
@@ -168,7 +165,7 @@ 

    * Called when a user session is started.  Argument is the tty allocated to

    * the session, or NULL if no tty was allocated.

    *

- @@ -172,13 +218,82 @@ audit_session_close(struct logininfo *li

+ @@ -172,13 +216,82 @@ audit_session_close(struct logininfo *li

   /*

    * This will be called when a user runs a non-interactive command.  Note that

    * it may be called multiple times for a single connection since SSH2 allows
@@ -177,8 +174,9 @@ 

  + * audit_end_command.

    */

  -void

+ -audit_run_command(const char *command)

  +int

-  audit_run_command(const char *command)

+ +audit_run_command(struct ssh *ssh, const char *command)

   {

   	debug("audit run command euid %d user %s command '%.200s'", geteuid(),

   	    audit_username(), command);
@@ -192,7 +190,7 @@ 

  + * the corresponding audit_run_command.

  + */

  +void

- +audit_end_command(int handle, const char *command)

+ +audit_end_command(struct ssh *ssh, int handle, const char *command)

  +{

  +	debug("audit end nopty exec  euid %d user %s command '%.200s'", geteuid(),

  +	    audit_username(), command);
@@ -204,7 +202,7 @@ 

  + * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key.

  + */

  +int

- +audit_keyusage(int host_user, char *fp, int rv)

+ +audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)

  +{

  +	debug("audit %s key usage euid %d user %s fingerprint %s, result %d",

  +		host_user ? "pubkey" : "hostbased", geteuid(), audit_username(),
@@ -215,7 +213,7 @@ 

  + * This will be called when the protocol negotiation fails.

  + */

  +void

- +audit_unsupported_body(int what)

+ +audit_unsupported_body(struct ssh *ssh, int what)

  +{

  +	debug("audit unsupported protocol euid %d type %d", geteuid(), what);

  +}
@@ -224,7 +222,7 @@ 

  + * This will be called on succesfull protocol negotiation.

  + */

  +void

- +audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid,

+ +audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid,

  +	       uid_t uid)

  +{

  +	debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u",
@@ -236,7 +234,7 @@ 

  + * This will be called on succesfull session key discard

  + */

  +void

- +audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)

+ +audit_session_key_free_body(struct ssh *, int ctos, pid_t pid, uid_t uid)

  +{

  +	debug("audit session key discard euid %u direction %d from pid %ld uid %u",

  +		(unsigned)geteuid(), ctos, (long)pid, (unsigned)uid);
@@ -246,25 +244,25 @@ 

  + * This will be called on destroy private part of the server key

  + */

  +void

- +audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)

+ +audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid)

  +{

  +	debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u",

  +		geteuid(), fp, (long)pid, (unsigned)uid);

   }

   # endif  /* !defined CUSTOM_SSH_AUDIT_EVENTS */

   #endif /* SSH_AUDIT_EVENTS */

- diff -up openssh-7.6p1/audit.h.audit openssh-7.6p1/audit.h

- --- openssh-7.6p1/audit.h.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/audit.h	2017-10-04 17:18:32.834505048 +0200

+ diff -up openssh/audit.h.audit openssh/audit.h

+ --- openssh/audit.h.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/audit.h	2019-04-03 17:02:20.713886041 +0200

  @@ -26,6 +26,7 @@

   # define _SSH_AUDIT_H

   

   #include "loginrec.h"

  +#include "sshkey.h"

   

-  enum ssh_audit_event_type {

-  	SSH_LOGIN_EXCEED_MAXTRIES,

- @@ -43,13 +44,32 @@ enum ssh_audit_event_type {

+  struct ssh;

+  

+ @@ -45,13 +46,32 @@ enum ssh_audit_event_type {

   	SSH_CONNECTION_ABANDON,	/* closed without completing auth */

   	SSH_AUDIT_UNKNOWN

   };
@@ -279,28 +277,28 @@ 

  +int	listening_for_clients(void);

  +

   void	audit_connection_from(const char *, int);

-  void	audit_event(ssh_audit_event_t);

+  void	audit_event(struct ssh *, ssh_audit_event_t);

  +void	audit_count_session_open(void);

   void	audit_session_open(struct logininfo *);

   void	audit_session_close(struct logininfo *);

  -void	audit_run_command(const char *);

- +int	audit_run_command(const char *);

- +void 	audit_end_command(int, const char *);

+ +int	audit_run_command(struct ssh *, const char *);

+ +void 	audit_end_command(struct ssh *, int, const char *);

   ssh_audit_event_t audit_classify_auth(const char *);

- +int	audit_keyusage(int, char *, int);

- +void	audit_key(int, int *, const struct sshkey *);

- +void	audit_unsupported(int);

- +void	audit_kex(int, char *, char *, char *, char *);

- +void	audit_unsupported_body(int);

- +void	audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t);

- +void	audit_session_key_free(int ctos);

- +void	audit_session_key_free_body(int ctos, pid_t, uid_t);

- +void	audit_destroy_sensitive_data(const char *, pid_t, uid_t);

+ +int	audit_keyusage(struct ssh *, int, char *, int);

+ +void	audit_key(struct ssh *, int, int *, const struct sshkey *);

+ +void	audit_unsupported(struct ssh *, int);

+ +void	audit_kex(struct ssh *, int, char *, char *, char *, char *);

+ +void	audit_unsupported_body(struct ssh *, int);

+ +void	audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t);

+ +void	audit_session_key_free(struct ssh *, int ctos);

+ +void	audit_session_key_free_body(struct ssh *, int ctos, pid_t, uid_t);

+ +void	audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t);

   

   #endif /* _SSH_AUDIT_H */

- diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c

- --- openssh-7.6p1/audit-linux.c.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/audit-linux.c	2017-10-04 17:18:32.835505053 +0200

+ diff -up openssh/audit-linux.c.audit openssh/audit-linux.c

+ --- openssh/audit-linux.c.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/audit-linux.c	2019-04-03 17:02:20.713886041 +0200

  @@ -33,27 +33,40 @@

   

   #include "log.h"
@@ -414,7 +412,7 @@ 

  +}

  +

  +int

- +audit_keyusage(int host_user, char *fp, int rv)

+ +audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)

  +{

  +	char buf[AUDIT_LOG_SIZE];

  +	int audit_fd, rc, saved_errno;
@@ -429,12 +427,12 @@ 

  +	}

  +	snprintf(buf, sizeof(buf), "%s_auth grantors=auth-key", host_user ? "pubkey" : "hostbased");

  +	rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,

- +		buf, audit_username(), -1, NULL, ssh_remote_ipaddr(active_state), NULL, rv);

+ +		buf, audit_username(), -1, NULL, ssh_remote_ipaddr(ssh), NULL, rv);

  +	if ((rc < 0) && ((rc != -1) || (getuid() == 0)))

  +		goto out;

  +	snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", fp);

  +	rc = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, buf, NULL,

- +		ssh_remote_ipaddr(active_state), NULL, rv);

+ +		ssh_remote_ipaddr(ssh), NULL, rv);

  +out:

  +	saved_errno = errno;

  +	audit_close(audit_fd);
@@ -448,34 +446,34 @@ 

   /* Below is the sshd audit API code */

   

   void

- @@ -76,24 +177,55 @@ audit_connection_from(const char *host,

+ @@ -76,49 +176,210 @@ audit_connection_from(const char *host,

   	/* not implemented */

   }

   

- -void

  +int

-  audit_run_command(const char *command)

-  {

- -	/* not implemented */

+ +audit_run_command(struct ssh *ssh, const char *command)

+ +{

  +	if (!user_login_count++)

  +		linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,

- +		    ssh_remote_ipaddr(active_state),

+ +		    ssh_remote_ipaddr(ssh),

  +		    "ssh", 1, AUDIT_USER_LOGIN);

  +	linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,

- +	    ssh_remote_ipaddr(active_state),

+ +	    ssh_remote_ipaddr(ssh),

  +	    "ssh", 1, AUDIT_USER_START);

  +	return 0;

  +}

  +

- +void

- +audit_end_command(int handle, const char *command)

- +{

+  void

+ -audit_run_command(const char *command)

+ +audit_end_command(struct ssh *ssh, int handle, const char *command)

+  {

+ -	/* not implemented */

  +	linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,

- +	    ssh_remote_ipaddr(active_state),

+ +	    ssh_remote_ipaddr(ssh),

  +	    "ssh", 1, AUDIT_USER_END);

  +	if (user_login_count && !--user_login_count)

  +		linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,

- +		    ssh_remote_ipaddr(active_state),

+ +		    ssh_remote_ipaddr(ssh),

  +		    "ssh", 1, AUDIT_USER_LOGOUT);

  +}

  +
@@ -510,9 +508,8 @@ 

   }

   

   void

- @@ -102,25 +231,155 @@ audit_event(ssh_audit_event_t event)

-  	struct ssh *ssh = active_state; /* XXX */

-  

+  audit_event(struct ssh *ssh, ssh_audit_event_t event)

+  {

   	switch(event) {

  -	case SSH_AUTH_SUCCESS:

  -	case SSH_CONNECTION_CLOSE:
@@ -563,7 +560,7 @@ 

   }

  +

  +void

- +audit_unsupported_body(int what)

+ +audit_unsupported_body(struct ssh *ssh, int what)

  +{

  +#ifdef AUDIT_CRYPTO_SESSION

  +	char buf[AUDIT_LOG_SIZE];
@@ -572,15 +569,15 @@ 

  +	int audit_fd;

  +

  +	snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ",

- +		name[what], ssh_remote_port(active_state), (s = get_local_ipaddr(packet_get_connection_in())),

- +		ssh_local_port(active_state));

+ +		name[what], ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))),

+ +		ssh_local_port(ssh));

  +	free(s);

  +	audit_fd = audit_open();

  +	if (audit_fd < 0)

  +		/* no problem, the next instruction will be fatal() */

  +		return;

  +	audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION,

- +			buf, NULL, ssh_remote_ipaddr(active_state), NULL, 0);

+ +			buf, NULL, ssh_remote_ipaddr(ssh), NULL, 0);

  +	audit_close(audit_fd);

  +#endif

  +}
@@ -588,7 +585,7 @@ 

  +const static char *direction[] = { "from-server", "from-client", "both" };

  +

  +void

- +audit_kex_body(int ctos, char *enc, char *mac, char *compress,

+ +audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress,

  +    char *pfs, pid_t pid, uid_t uid)

  +{

  +#ifdef AUDIT_CRYPTO_SESSION
@@ -600,7 +597,7 @@ 

  +	snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s pfs=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",

  +		direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, pfs,

  +		(intmax_t)pid, (intmax_t)uid,

- +		ssh_remote_port(active_state), (s = get_local_ipaddr(packet_get_connection_in())), ssh_local_port(active_state));

+ +		ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ssh_local_port(ssh));

  +	free(s);

  +	audit_fd = audit_open();

  +	if (audit_fd < 0) {
@@ -611,7 +608,7 @@ 

  +			fatal("cannot open audit"); /* Must prevent login */

  +	}

  +	audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION,

- +			buf, NULL, ssh_remote_ipaddr(active_state), NULL, 1);

+ +			buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1);

  +	audit_close(audit_fd);

  +	/* do not abort if the error is EPERM and sshd is run as non root user */

  +	if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
@@ -620,7 +617,7 @@ 

  +}

  +

  +void

- +audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)

+ +audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid)

  +{

  +	char buf[AUDIT_LOG_SIZE];

  +	int audit_fd, audit_ok;
@@ -628,9 +625,9 @@ 

  +

  +	snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",

  +		 direction[ctos], (intmax_t)pid, (intmax_t)uid,

- +		 ssh_remote_port(active_state),

- +		 (s = get_local_ipaddr(packet_get_connection_in())),

- +		 ssh_local_port(active_state));

+ +		 ssh_remote_port(ssh),

+ +		 (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))),

+ +		 ssh_local_port(ssh));

  +	free(s);

  +	audit_fd = audit_open();

  +	if (audit_fd < 0) {
@@ -640,7 +637,7 @@ 

  +		return;

  +	}

  +	audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,

- +			buf, NULL, ssh_remote_ipaddr(active_state), NULL, 1);

+ +			buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1);

  +	audit_close(audit_fd);

  +	/* do not abort if the error is EPERM and sshd is run as non root user */

  +	if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
@@ -648,7 +645,7 @@ 

  +}

  +

  +void

- +audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)

+ +audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid)

  +{

  +	char buf[AUDIT_LOG_SIZE];

  +	int audit_fd, audit_ok;
@@ -664,7 +661,7 @@ 

  +	}

  +	audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,

  +			buf, NULL,

- +			listening_for_clients() ? NULL : ssh_remote_ipaddr(active_state),

+ +			listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh),

  +			NULL, 1);

  +	audit_close(audit_fd);

  +	/* do not abort if the error is EPERM and sshd is run as non root user */
@@ -672,10 +669,10 @@ 

  +		error("cannot write into audit");

  +}

   #endif /* USE_LINUX_AUDIT */

- diff -up openssh-7.6p1/auditstub.c.audit openssh-7.6p1/auditstub.c

- --- openssh-7.6p1/auditstub.c.audit	2017-10-04 17:18:32.835505053 +0200

- +++ openssh-7.6p1/auditstub.c	2017-10-04 17:18:32.835505053 +0200

- @@ -0,0 +1,50 @@

+ diff -up openssh/auditstub.c.audit openssh/auditstub.c

+ --- openssh/auditstub.c.audit	2019-04-03 17:02:20.714886050 +0200

+ +++ openssh/auditstub.c	2019-04-03 17:02:20.714886050 +0200

+ @@ -0,0 +1,52 @@

  +/* $Id: auditstub.c,v 1.1 jfch Exp $ */

  +

  +/*
@@ -707,95 +704,97 @@ 

  +

  +#include <sys/types.h>

  +

+ +struct ssh;

+ +

  +void

- +audit_unsupported(int n)

+ +audit_unsupported(struct ssh *ssh, int n)

  +{

  +}

  +

  +void

- +audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs)

+ +audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs)

  +{

  +}

  +

  +void

- +audit_session_key_free(int ctos)

+ +audit_session_key_free(struct ssh *ssh, int ctos)

  +{

  +}

  +

  +void

- +audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)

+ +audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid)

  +{

  +}

- diff -up openssh-7.6p1/auth2.c.audit openssh-7.6p1/auth2.c

- --- openssh-7.6p1/auth2.c.audit	2017-10-04 17:18:32.746504598 +0200

- +++ openssh-7.6p1/auth2.c	2017-10-04 17:18:32.835505053 +0200

- @@ -255,9 +255,6 @@ input_userauth_request(int type, u_int32

+ diff -up openssh/auth2.c.audit openssh/auth2.c

+ --- openssh/auth2.c.audit	2019-04-03 17:02:20.651885453 +0200

+ +++ openssh/auth2.c	2019-04-03 17:02:20.714886050 +0200

+ @@ -303,9 +303,6 @@ input_userauth_request(int type, u_int32

   		} else {

   			/* Invalid user, fake password information */

   			authctxt->pw = fakepw();

  -#ifdef SSH_AUDIT_EVENTS

- -			PRIVSEP(audit_event(SSH_INVALID_USER));

+ -			PRIVSEP(audit_event(ssh, SSH_INVALID_USER));

  -#endif

   		}

   #ifdef USE_PAM

   		if (options.use_pam)

- diff -up openssh-7.6p1/auth2-hostbased.c.audit openssh-7.6p1/auth2-hostbased.c

- --- openssh-7.6p1/auth2-hostbased.c.audit	2017-10-04 17:18:32.683504276 +0200

- +++ openssh-7.6p1/auth2-hostbased.c	2017-10-04 17:18:32.835505053 +0200

- @@ -152,7 +152,7 @@ userauth_hostbased(struct ssh *ssh)

-  	/* test for allowed key and correct signature */

+ diff -up openssh/auth2-hostbased.c.audit openssh/auth2-hostbased.c

+ --- openssh/auth2-hostbased.c.audit	2019-04-03 17:02:20.612885083 +0200

+ +++ openssh/auth2-hostbased.c	2019-04-03 17:02:20.714886050 +0200

+ @@ -158,7 +158,7 @@ userauth_hostbased(struct ssh *ssh)

   	authenticated = 0;

-  	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&

+  	if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser,

+  	    chost, key)) &&

  -	    PRIVSEP(sshkey_verify(key, sig, slen,

- +	    PRIVSEP(hostbased_key_verify(key, sig, slen,

+ +	    PRIVSEP(hostbased_key_verify(ssh, key, sig, slen,

   	    sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0)

   		authenticated = 1;

   

- @@ -169,6 +169,19 @@ done:

+ @@ -175,6 +175,19 @@ done:

   	return authenticated;

   }

   

  +int

- +hostbased_key_verify(const struct sshkey *key, const u_char *sig, size_t slen,

- +    const u_char *data, size_t datalen, const char *pkalg, u_int compat)

+ +hostbased_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig,

+ +    size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat)

  +{

  +	int rv;

  +

  +	rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat);

  +#ifdef SSH_AUDIT_EVENTS

- +	audit_key(0, &rv, key);

+ +	audit_key(ssh, 0, &rv, key);

  +#endif

  +	return rv;

  +}

  +

   /* return 1 if given hostkey is allowed */

   int

-  hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,

- diff -up openssh-7.6p1/auth2-pubkey.c.audit openssh-7.6p1/auth2-pubkey.c

- --- openssh-7.6p1/auth2-pubkey.c.audit	2017-10-04 17:18:32.828505018 +0200

- +++ openssh-7.6p1/auth2-pubkey.c	2017-10-04 17:18:32.835505053 +0200

- @@ -206,7 +206,7 @@ userauth_pubkey(struct ssh *ssh)

+  hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,

+ diff -up openssh/auth2-pubkey.c.audit openssh/auth2-pubkey.c

+ --- openssh/auth2-pubkey.c.audit	2019-04-03 17:02:20.691885832 +0200

+ +++ openssh/auth2-pubkey.c	2019-04-03 17:02:20.714886050 +0200

+ @@ -219,7 +219,7 @@ userauth_pubkey(struct ssh *ssh)

   		/* test for correct signature */

   		authenticated = 0;

   		if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&

  -		    PRIVSEP(sshkey_verify(key, sig, slen,

- +		    PRIVSEP(user_key_verify(key, sig, slen,

+ +		    PRIVSEP(user_key_verify(ssh, key, sig, slen,

   		    sshbuf_ptr(b), sshbuf_len(b),

   		    (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL,

   		    ssh->compat)) == 0) {

- @@ -250,6 +250,19 @@ done:

+ @@ -278,6 +278,19 @@ done:

   	return authenticated;

   }

   

  +int

- +user_key_verify(const struct sshkey *key, const u_char *sig, size_t slen,

- +    const u_char *data, size_t datalen, const char *pkalg, u_int compat)

+ +user_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig,

+ +    size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat)

  +{

  +	int rv;

  +

  +	rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat);

  +#ifdef SSH_AUDIT_EVENTS

- +	audit_key(1, &rv, key);

+ +	audit_key(ssh, 1, &rv, key);

  +#endif

  +	return rv;

  +}
@@ -803,52 +802,52 @@ 

   static int

   match_principals_option(const char *principal_list, struct sshkey_cert *cert)

   {

- diff -up openssh-7.6p1/auth.c.audit openssh-7.6p1/auth.c

- --- openssh-7.6p1/auth.c.audit	2017-10-04 17:18:32.746504598 +0200

- +++ openssh-7.6p1/auth.c	2017-10-04 17:18:32.835505053 +0200

- @@ -360,7 +360,7 @@ auth_log(Authctxt *authctxt, int authent

+ diff -up openssh/auth.c.audit openssh/auth.c

+ --- openssh/auth.c.audit	2019-04-03 17:02:20.691885832 +0200

+ +++ openssh/auth.c	2019-04-03 17:02:20.714886050 +0200

+ @@ -366,7 +366,7 @@ auth_log(struct ssh *ssh, int authentica

   # endif

   #endif

   #ifdef SSH_AUDIT_EVENTS

  -	if (authenticated == 0 && !authctxt->postponed)

  +	if (authenticated == 0 && !authctxt->postponed && !partial)

-  		audit_event(audit_classify_auth(method));

+  		audit_event(ssh, audit_classify_auth(method));

   #endif

   }

- @@ -599,9 +599,6 @@ getpwnamallow(const char *user)

-  		record_failed_login(user,

+ @@ -592,9 +592,6 @@ getpwnamallow(struct ssh *ssh, const cha

+  		record_failed_login(ssh, user,

   		    auth_get_canonical_hostname(ssh, options.use_dns), "ssh");

   #endif

  -#ifdef SSH_AUDIT_EVENTS

- -		audit_event(SSH_INVALID_USER);

+ -		audit_event(ssh, SSH_INVALID_USER);

  -#endif /* SSH_AUDIT_EVENTS */

   		return (NULL);

   	}

-  	if (!allowed_user(pw))

- diff -up openssh-7.6p1/auth.h.audit openssh-7.6p1/auth.h

- --- openssh-7.6p1/auth.h.audit	2017-10-04 17:18:32.768504711 +0200

- +++ openssh-7.6p1/auth.h	2017-10-04 17:18:32.836505059 +0200

- @@ -198,6 +198,8 @@ struct passwd * getpwnamallow(const char

+  	if (!allowed_user(ssh, pw))

+ diff -up openssh/auth.h.audit openssh/auth.h

+ --- openssh/auth.h.audit	2019-04-03 17:02:20.692885842 +0200

+ +++ openssh/auth.h	2019-04-03 17:02:20.714886050 +0200

+ @@ -195,6 +195,8 @@ struct passwd * getpwnamallow(struct ssh

   

   char	*expand_authorized_keys(const char *, struct passwd *pw);

   char	*authorized_principals_file(struct passwd *);

- +int	 user_key_verify(const struct sshkey *, const u_char *, size_t,

+ +int	 user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t,

  +    const u_char *, size_t, const char *, u_int);

   

   FILE	*auth_openkeyfile(const char *, struct passwd *, int);

   FILE	*auth_openprincipals(const char *, struct passwd *, int);

- @@ -217,6 +218,8 @@ struct sshkey	*get_hostkey_private_by_ty

+ @@ -214,6 +216,8 @@ struct sshkey	*get_hostkey_private_by_ty

   int	 get_hostkey_index(struct sshkey *, int, struct ssh *);

-  int	 sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **,

-  	     size_t *, const u_char *, size_t, const char *, u_int);

- +int	 hostbased_key_verify(const struct sshkey *, const u_char *, size_t,

+  int	 sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *,

+      u_char **, size_t *, const u_char *, size_t, const char *);

+ +int	 hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t,

  +    const u_char *, size_t, const char *, u_int);

   

   /* Key / cert options linkage to auth layer */

   const struct sshauthopt *auth_options(struct ssh *);

- diff -up openssh-7.6p1/cipher.c.audit openssh-7.6p1/cipher.c

- --- openssh-7.6p1/cipher.c.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/cipher.c	2017-10-04 17:18:32.836505059 +0200

+ diff -up openssh/cipher.c.audit openssh/cipher.c

+ --- openssh/cipher.c.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/cipher.c	2019-04-03 17:02:20.714886050 +0200

  @@ -61,25 +61,6 @@ struct sshcipher_ctx {

   	const struct sshcipher *cipher;

   };
@@ -875,7 +874,7 @@ 

   static const struct sshcipher ciphers[] = {

   #ifdef WITH_OPENSSL

   #ifndef OPENSSL_NO_DES

- @@ -409,7 +409,7 @@ cipher_get_length(struct sshcipher_ctx *

+ @@ -410,7 +391,7 @@ cipher_get_length(struct sshcipher_ctx *

   void

   cipher_free(struct sshcipher_ctx *cc)

   {
@@ -884,9 +883,9 @@ 

   		return;

   	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)

   		explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));

- diff -up openssh-7.6p1/cipher.h.audit openssh-7.6p1/cipher.h

- --- openssh-7.6p1/cipher.h.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/cipher.h	2017-10-04 17:18:32.836505059 +0200

+ diff -up openssh/cipher.h.audit openssh/cipher.h

+ --- openssh/cipher.h.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/cipher.h	2019-04-03 17:02:20.714886050 +0200

  @@ -45,7 +45,25 @@

   #define CIPHER_ENCRYPT		1

   #define CIPHER_DECRYPT		0
@@ -914,10 +913,10 @@ 

   struct sshcipher_ctx;

   

   const struct sshcipher *cipher_by_name(const char *);

- diff -up openssh-7.6p1/kex.c.audit openssh-7.6p1/kex.c

- --- openssh-7.6p1/kex.c.audit	2017-10-04 17:18:32.822504987 +0200

- +++ openssh-7.6p1/kex.c	2017-10-04 17:18:32.836505059 +0200

- @@ -54,6 +54,7 @@

+ diff -up openssh/kex.c.audit openssh/kex.c

+ --- openssh/kex.c.audit	2019-04-03 17:02:20.652885462 +0200

+ +++ openssh/kex.c	2019-04-03 17:02:20.715886060 +0200

+ @@ -60,6 +60,7 @@

   #include "ssherr.h"

   #include "sshbuf.h"

   #include "digest.h"
@@ -925,64 +924,91 @@ 

   

   #ifdef GSSAPI

   #include "ssh-gss.h"

- @@ -692,8 +693,12 @@ choose_enc(struct sshenc *enc, char *cli

+ @@ -758,12 +759,16 @@ kex_start_rekex(struct ssh *ssh)

+  }

+  

+  static int

+ -choose_enc(struct sshenc *enc, char *client, char *server)

+ +choose_enc(struct ssh *ssh, struct sshenc *enc, char *client, char *server)

   {

   	char *name = match_list(client, server, NULL);

   

  -	if (name == NULL)

  +	if (name == NULL) {

  +#ifdef SSH_AUDIT_EVENTS

- +		audit_unsupported(SSH_AUDIT_UNSUPPORTED_CIPHER);

+ +		audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_CIPHER);

  +#endif

   		return SSH_ERR_NO_CIPHER_ALG_MATCH;

  +	}

   	if ((enc->cipher = cipher_by_name(name)) == NULL) {

   		free(name);

   		return SSH_ERR_INTERNAL_ERROR;

- @@ -713,8 +718,12 @@ choose_mac(struct ssh *ssh, struct sshma

+ @@ -783,8 +788,12 @@ choose_mac(struct ssh *ssh, struct sshma

   {

   	char *name = match_list(client, server, NULL);

   

  -	if (name == NULL)

  +	if (name == NULL) {

  +#ifdef SSH_AUDIT_EVENTS

- +		audit_unsupported(SSH_AUDIT_UNSUPPORTED_MAC);

+ +		audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_MAC);

  +#endif

   		return SSH_ERR_NO_MAC_ALG_MATCH;

  +	}

   	if (mac_setup(mac, name) < 0) {

   		free(name);

   		return SSH_ERR_INTERNAL_ERROR;

- @@ -733,8 +742,12 @@ choose_comp(struct sshcomp *comp, char *

+ @@ -796,12 +805,16 @@ choose_mac(struct ssh *ssh, struct sshma

+  }

+  

+  static int

+ -choose_comp(struct sshcomp *comp, char *client, char *server)

+ +choose_comp(struct ssh *ssh, struct sshcomp *comp, char *client, char *server)

   {

   	char *name = match_list(client, server, NULL);

   

  -	if (name == NULL)

  +	if (name == NULL) {

  +#ifdef SSH_AUDIT_EVENTS

- +		audit_unsupported(SSH_AUDIT_UNSUPPORTED_COMPRESSION);

+ +		audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_COMPRESSION);

  +#endif

   		return SSH_ERR_NO_COMPRESS_ALG_MATCH;

  +	}

   	if (strcmp(name, "zlib@openssh.com") == 0) {

   		comp->type = COMP_DELAYED;

   	} else if (strcmp(name, "zlib") == 0) {

- @@ -904,6 +917,10 @@ kex_choose_conf(struct ssh *ssh)

+ @@ -933,7 +946,7 @@ kex_choose_conf(struct ssh *ssh)

+  		nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;

+  		nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;

+  		ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;

+ -		if ((r = choose_enc(&newkeys->enc, cprop[nenc],

+ +		if ((r = choose_enc(ssh, &newkeys->enc, cprop[nenc],

+  		    sprop[nenc])) != 0) {

+  			kex->failed_choice = peer[nenc];

+  			peer[nenc] = NULL;

+ @@ -948,7 +961,7 @@ kex_choose_conf(struct ssh *ssh)

+  			peer[nmac] = NULL;

+  			goto out;

+  		}

+ -		if ((r = choose_comp(&newkeys->comp, cprop[ncomp],

+ +		if ((r = choose_comp(ssh, &newkeys->comp, cprop[ncomp],

+  		    sprop[ncomp])) != 0) {

+  			kex->failed_choice = peer[ncomp];

+  			peer[ncomp] = NULL;

+ @@ -971,6 +984,10 @@ kex_choose_conf(struct ssh *ssh)

   		dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);

   		dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);

   		dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);

  +		debug("kex: %s need=%d dh_need=%d", kex->name, need, dh_need);

  +#ifdef SSH_AUDIT_EVENTS

- +		audit_kex(mode, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name, kex->name);

+ +		audit_kex(ssh, mode, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name, kex->name);

  +#endif

   	}

   	/* XXX need runden? */

   	kex->we_need = need;

- @@ -1037,3 +1054,33 @@ dump_digest(char *msg, u_char *digest, i

-  	sshbuf_dump_data(digest, len, stderr);

+ @@ -1129,6 +1146,36 @@ dump_digest(const char *msg, const u_cha

   }

   #endif

- +

+  

  +static void

  +enc_destroy(struct sshenc *enc)

  +{
@@ -1012,22 +1038,26 @@ 

  +	mac_destroy(&newkeys->mac);

  +	memset(&newkeys->comp, 0, sizeof(newkeys->comp));

  +}

- diff -up openssh-7.6p1/kex.h.audit openssh-7.6p1/kex.h

- --- openssh-7.6p1/kex.h.audit	2017-10-04 17:18:32.822504987 +0200

- +++ openssh-7.6p1/kex.h	2017-10-04 17:18:32.836505059 +0200

- @@ -219,6 +219,8 @@ int	 kexgss_client(struct ssh *);

+ +

+  /*

+   * Send a plaintext error message to the peer, suffixed by \r\n.

+   * Only used during banner exchange, and there only for the server.

+ diff -up openssh/kex.h.audit openssh/kex.h

+ --- openssh/kex.h.audit	2019-04-03 17:02:20.652885462 +0200

+ +++ openssh/kex.h	2019-04-03 17:02:20.715886060 +0200

+ @@ -226,6 +226,8 @@ int	 kexgss_client(struct ssh *);

   int	 kexgss_server(struct ssh *);

   #endif

   

  +void	newkeys_destroy(struct newkeys *newkeys);

  +

-  int	 kex_dh_hash(int, const char *, const char *,

-      const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,

-      const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);

- diff -up openssh-7.6p1/mac.c.audit openssh-7.6p1/mac.c

- --- openssh-7.6p1/mac.c.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/mac.c	2017-10-04 17:18:32.836505059 +0200

- @@ -242,6 +242,20 @@ mac_clear(struct sshmac *mac)

+  int	 kex_dh_keypair(struct kex *);

+  int	 kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **,

+      struct sshbuf **);

+ diff -up openssh/mac.c.audit openssh/mac.c

+ --- openssh/mac.c.audit	2019-04-03 17:02:20.652885462 +0200

+ +++ openssh/mac.c	2019-04-03 17:02:20.715886060 +0200

+ @@ -243,6 +243,20 @@ mac_clear(struct sshmac *mac)

   	mac->umac_ctx = NULL;

   }

   
@@ -1048,9 +1078,9 @@ 

   /* XXX copied from ciphers_valid */

   #define	MAC_SEP	","

   int

- diff -up openssh-7.6p1/mac.h.audit openssh-7.6p1/mac.h

- --- openssh-7.6p1/mac.h.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/mac.h	2017-10-04 17:18:32.837505064 +0200

+ diff -up openssh/mac.h.audit openssh/mac.h

+ --- openssh/mac.h.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/mac.h	2019-04-03 17:02:20.715886060 +0200

  @@ -49,5 +49,6 @@ int	 mac_compute(struct sshmac *, u_int3

   int	 mac_check(struct sshmac *, u_int32_t, const u_char *, size_t,

       const u_char *, size_t);
@@ -1058,23 +1088,23 @@ 

  +void	 mac_destroy(struct sshmac *);

   

   #endif /* SSHMAC_H */

- diff -up openssh-7.6p1/Makefile.in.audit openssh-7.6p1/Makefile.in

- --- openssh-7.6p1/Makefile.in.audit	2017-10-04 17:18:32.749504614 +0200

- +++ openssh-7.6p1/Makefile.in	2017-10-04 17:18:32.837505064 +0200

- @@ -100,7 +100,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \

-  	kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \

-  	kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \

-  	kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \

+ diff -up openssh/Makefile.in.audit openssh/Makefile.in

+ --- openssh/Makefile.in.audit	2019-04-03 17:02:20.705885965 +0200

+ +++ openssh/Makefile.in	2019-04-03 17:02:20.715886060 +0200

+ @@ -109,7 +109,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \

+  	kexgexc.o kexgexs.o \

+  	sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \

+  	kexgssc.o \

  -	platform-pledge.o platform-tracing.o platform-misc.o

  +	platform-pledge.o platform-tracing.o platform-misc.o \

  +	auditstub.o

   

+  

   SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \

-  	sshconnect.o sshconnect2.o mux.o

- diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c

- --- openssh-7.6p1/monitor.c.audit	2017-10-04 17:18:32.824504997 +0200

- +++ openssh-7.6p1/monitor.c	2017-10-04 17:18:32.837505064 +0200

- @@ -102,6 +102,7 @@

+ diff -up openssh/monitor.c.audit openssh/monitor.c

+ --- openssh/monitor.c.audit	2019-04-03 17:02:20.674885671 +0200

+ +++ openssh/monitor.c	2019-04-03 17:03:17.201421405 +0200

+ @@ -93,6 +93,7 @@

   #include "compat.h"

   #include "ssh2.h"

   #include "authfd.h"
@@ -1082,28 +1112,28 @@ 

   #include "match.h"

   #include "ssherr.h"

   

- @@ -117,6 +118,8 @@ extern Buffer auth_debug;

+ @@ -107,6 +108,8 @@ extern u_char session_id[];

   extern struct sshbuf *loginmsg;

   extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */

   

- +extern void destroy_sensitive_data(int);

+ +extern void destroy_sensitive_data(struct ssh *, int);

  +

   /* State exported from the child */

   static struct sshbuf *child_state;

   

- @@ -167,6 +170,11 @@ int mm_answer_gss_updatecreds(int, Buffe

+ @@ -157,6 +160,11 @@ int mm_answer_gss_updatecreds(struct ssh

   #ifdef SSH_AUDIT_EVENTS

-  int mm_answer_audit_event(int, struct sshbuf *);

-  int mm_answer_audit_command(int, struct sshbuf *);

- +int mm_answer_audit_end_command(int, struct sshbuf *);

- +int mm_answer_audit_unsupported_body(int, struct sshbuf *);

- +int mm_answer_audit_kex_body(int, struct sshbuf *);

- +int mm_answer_audit_session_key_free_body(int, struct sshbuf *);

- +int mm_answer_audit_server_key_free(int, struct sshbuf *);

+  int mm_answer_audit_event(struct ssh *, int, struct sshbuf *);

+  int mm_answer_audit_command(struct ssh *, int, struct sshbuf *);

+ +int mm_answer_audit_end_command(struct ssh *, int, struct sshbuf *);

+ +int mm_answer_audit_unsupported_body(struct ssh *, int, struct sshbuf *);

+ +int mm_answer_audit_kex_body(struct ssh *, int, struct sshbuf *);

+ +int mm_answer_audit_session_key_free_body(struct ssh *, int, struct sshbuf *);

+ +int mm_answer_audit_server_key_free(struct ssh *, int, struct sshbuf *);

   #endif

   

-  static int monitor_read_log(struct monitor *);

- @@ -222,6 +230,10 @@ struct mon_table mon_dispatch_proto20[]

+  static Authctxt *authctxt;

+ @@ -215,6 +223,10 @@ struct mon_table mon_dispatch_proto20[]

   #endif

   #ifdef SSH_AUDIT_EVENTS

       {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
@@ -1114,7 +1144,7 @@ 

   #endif

   #ifdef BSD_AUTH

       {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},

- @@ -260,6 +272,11 @@ struct mon_table mon_dispatch_postauth20

+ @@ -249,6 +261,11 @@ struct mon_table mon_dispatch_postauth20

   #ifdef SSH_AUDIT_EVENTS

       {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},

       {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
@@ -1126,7 +1156,7 @@ 

   #endif

       {0, 0, NULL}

   };

- @@ -1396,8 +1413,10 @@ mm_answer_keyverify(int sock, struct ssh

+ @@ -1445,8 +1462,10 @@ mm_answer_keyverify(struct ssh *ssh, int

   	char *sigalg;

   	size_t signaturelen, datalen, bloblen;

   	int r, ret, valid_data = 0, encoded_ret;
@@ -1138,7 +1168,7 @@ 

   	    (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 ||

   	    (r = sshbuf_get_string(m, &data, &datalen)) != 0 ||

   	    (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0)

- @@ -1405,6 +1424,8 @@ mm_answer_keyverify(int sock, struct ssh

+ @@ -1455,6 +1474,8 @@ mm_answer_keyverify(struct ssh *ssh, int

   	if (hostbased_cuser == NULL || hostbased_chost == NULL ||

   	  !monitor_allowed_key(blob, bloblen))

   		fatal("%s: bad key, not previously allowed", __func__);
@@ -1147,18 +1177,18 @@ 

   

   	/* Empty signature algorithm means NULL. */

   	if (*sigalg == '\0') {

- @@ -1414,21 +1435,24 @@ mm_answer_keyverify(int sock, struct ssh

+ @@ -1470,21 +1491,24 @@ mm_answer_keyverify(struct ssh *ssh, int

   	case MM_USERKEY:

   		valid_data = monitor_valid_userblob(data, datalen);

   		auth_method = "publickey";

- +		ret = user_key_verify(key, signature, signaturelen, data,

- +		    datalen, sigalg, active_state->compat);

+ +		ret = user_key_verify(ssh, key, signature, signaturelen, data,

+ +		    datalen, sigalg, ssh->compat);

   		break;

   	case MM_HOSTKEY:

   		valid_data = monitor_valid_hostbasedblob(data, datalen,

   		    hostbased_cuser, hostbased_chost);

- +		ret = hostbased_key_verify(key, signature, signaturelen, data,

- +		    datalen, sigalg, active_state->compat);

+ +		ret = hostbased_key_verify(ssh, key, signature, signaturelen, data,

+ +		    datalen, sigalg, ssh->compat);

   		auth_method = "hostbased";

   		break;

   	default:
@@ -1170,33 +1200,59 @@ 

   		fatal("%s: bad signature data blob", __func__);

   

  -	ret = sshkey_verify(key, signature, signaturelen, data, datalen,

- -	    sigalg, active_state->compat);

+ -	    sigalg, ssh->compat);

   	debug3("%s: %s %p signature %s", __func__, auth_method, key,

   	    (ret == 0) ? "verified" : "unverified");

   	auth2_record_key(authctxt, ret == 0, key);

- @@ -1485,6 +1509,12 @@ mm_session_close(Session *s)

+ @@ -1536,13 +1560,19 @@ mm_record_login(struct ssh *ssh, Session

+  }

+  

+  static void

+ -mm_session_close(Session *s)

+ +mm_session_close(struct ssh *ssh, Session *s)

+  {

+  	debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);

+  	if (s->ttyfd != -1) {

   		debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);

   		session_pty_cleanup2(s);

   	}

  +#ifdef SSH_AUDIT_EVENTS

  +	if (s->command != NULL) {

  +		debug3("%s: command %d", __func__, s->command_handle);

- +		session_end_command2(s);

+ +		session_end_command2(ssh, s);

  +	}

  +#endif

   	session_unused(s->self);

   }

   

- @@ -1588,6 +1618,8 @@ mm_answer_term(int sock, Buffer *req)

+ @@ -1609,7 +1639,7 @@ mm_answer_pty(struct ssh *ssh, int sock,

+  

+   error:

+  	if (s != NULL)

+ -		mm_session_close(s);

+ +		mm_session_close(ssh, s);

+  	if ((r = sshbuf_put_u32(m, 0)) != 0)

+  		fatal("%s: buffer error: %s", __func__, ssh_err(r));

+  	mm_request_send(sock, MONITOR_ANS_PTY, m);

+ @@ -1628,7 +1658,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, i

+  	if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0)

+  		fatal("%s: buffer error: %s", __func__, ssh_err(r));

+  	if ((s = session_by_tty(tty)) != NULL)

+ -		mm_session_close(s);

+ +		mm_session_close(ssh, s);

+  	sshbuf_reset(m);

+  	free(tty);

+  	return (0);

+ @@ -1650,6 +1680,8 @@ mm_answer_term(struct ssh *ssh, int sock

   		sshpam_cleanup();

   #endif

   

- +	destroy_sensitive_data(0);

+ +	destroy_sensitive_data(ssh, 0);

  +

   	while (waitpid(pmonitor->m_pid, &status, 0) == -1)

   		if (errno != EINTR)

   			exit(1);

- @@ -1630,12 +1662,47 @@ mm_answer_audit_command(int socket, Buff

+ @@ -1696,12 +1728,47 @@ mm_answer_audit_command(struct ssh *ssh,

   {

   	char *cmd;

   	int r;
@@ -1213,7 +1269,7 @@ 

  +		fatal("%s: error allocating a session", __func__);

  +	s->command = cmd;

  +#ifdef SSH_AUDIT_EVENTS

- +	s->command_handle = audit_run_command(cmd);

+ +	s->command_handle = audit_run_command(ssh, cmd);

  +#endif

  +

  +	sshbuf_reset(m);
@@ -1225,7 +1281,7 @@ 

  +}

  +

  +int

- +mm_answer_audit_end_command(int socket, struct sshbuf *m)

+ +mm_answer_audit_end_command(struct ssh *ssh, int socket, struct sshbuf *m)

  +{

  +	int handle, r;

  +	size_t len;
@@ -1241,19 +1297,19 @@ 

  +	if (s == NULL || s->ttyfd != -1 || s->command == NULL ||

  +	    strcmp(s->command, cmd) != 0)

  +		fatal("%s: invalid handle", __func__);

- +	mm_session_close(s);

+ +	mm_session_close(ssh, s);

   	free(cmd);

   	return (0);

   }

- @@ -1702,6 +1768,7 @@ monitor_apply_keystate(struct monitor *p

+ @@ -1767,6 +1834,7 @@ monitor_apply_keystate(struct ssh *ssh,

   void

-  mm_get_keystate(struct monitor *pmonitor)

+  mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor)

   {

  +	struct sshbuf *m;

   	debug3("%s: Waiting for new keys", __func__);

   

   	if ((child_state = sshbuf_new()) == NULL)

- @@ -1709,6 +1776,19 @@ mm_get_keystate(struct monitor *pmonitor

+ @@ -1774,6 +1842,19 @@ mm_get_keystate(struct ssh *ssh, struct

   	mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT,

   	    child_state);

   	debug3("%s: GOT new keys", __func__);
@@ -1262,7 +1318,7 @@ 

  +	m = sshbuf_new();

  +	mm_request_receive_expect(pmonitor->m_sendfd,

  +				  MONITOR_REQ_AUDIT_SESSION_KEY_FREE, m);

- +	mm_answer_audit_session_key_free_body(pmonitor->m_sendfd, m);

+ +	mm_answer_audit_session_key_free_body(ssh, pmonitor->m_sendfd, m);

  +	sshbuf_free(m);

  +#endif

  +
@@ -1273,20 +1329,20 @@ 

   }

   

   

- @@ -1976,3 +2056,102 @@ mm_answer_gss_updatecreds(int socket, Bu

+ @@ -2066,3 +2147,102 @@ mm_answer_gss_updatecreds(struct ssh *ss

   

   #endif /* GSSAPI */

   

  +#ifdef SSH_AUDIT_EVENTS

  +int

- +mm_answer_audit_unsupported_body(int sock, struct sshbuf *m)

+ +mm_answer_audit_unsupported_body(struct ssh *ssh, int sock, struct sshbuf *m)

  +{

  +	int what, r;

  +

  +	if ((r = sshbuf_get_u32(m, &what)) != 0)

  +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

  +

- +	audit_unsupported_body(what);

+ +	audit_unsupported_body(ssh, what);

  +

  +	sshbuf_reset(m);

  +
@@ -1295,7 +1351,7 @@ 

  +}

  +

  +int

- +mm_answer_audit_kex_body(int sock, struct sshbuf *m)

+ +mm_answer_audit_kex_body(struct ssh *ssh, int sock, struct sshbuf *m)

  +{

  +	int ctos, r;

  +	char *cipher, *mac, *compress, *pfs;
@@ -1315,7 +1371,7 @@ 

  +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

  +	uid = (pid_t) tmp;

  +

- +	audit_kex_body(ctos, cipher, mac, compress, pfs, pid, uid);

+ +	audit_kex_body(ssh, ctos, cipher, mac, compress, pfs, pid, uid);

  +

  +	free(cipher);

  +	free(mac);
@@ -1328,7 +1384,7 @@ 

  +}

  +

  +int

- +mm_answer_audit_session_key_free_body(int sock, struct sshbuf *m)

+ +mm_answer_audit_session_key_free_body(struct ssh *ssh, int sock, struct sshbuf *m)

  +{

  +	int ctos, r;

  +	u_int64_t tmp;
@@ -1343,7 +1399,7 @@ 

  +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

  +	uid = (uid_t) tmp;

  +

- +	audit_session_key_free_body(ctos, pid, uid);

+ +	audit_session_key_free_body(ssh, ctos, pid, uid);

  +

  +	sshbuf_reset(m);

  +
@@ -1352,7 +1408,7 @@ 

  +}

  +

  +int

- +mm_answer_audit_server_key_free(int sock, struct sshbuf *m)

+ +mm_answer_audit_server_key_free(struct ssh *ssh, int sock, struct sshbuf *m)

  +{

  +	size_t len, r;

  +	char *fp;
@@ -1368,7 +1424,7 @@ 

  +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

  +	uid = (uid_t) tmp;

  +

- +	audit_destroy_sensitive_data(fp, pid, uid);

+ +	audit_destroy_sensitive_data(ssh, fp, pid, uid);

  +

  +	free(fp);

  +	sshbuf_reset(m);
@@ -1376,10 +1432,10 @@ 

  +	return 0;

  +}

  +#endif /* SSH_AUDIT_EVENTS */

- diff -up openssh-7.6p1/monitor.h.audit openssh-7.6p1/monitor.h

- --- openssh-7.6p1/monitor.h.audit	2017-10-04 17:18:32.781504777 +0200

- +++ openssh-7.6p1/monitor.h	2017-10-04 17:18:32.837505064 +0200

- @@ -69,7 +69,13 @@ enum monitor_reqtype {

+ diff -up openssh/monitor.h.audit openssh/monitor.h

+ --- openssh/monitor.h.audit	2019-04-03 17:02:20.674885671 +0200

+ +++ openssh/monitor.h	2019-04-03 17:02:20.715886060 +0200

+ @@ -65,7 +65,13 @@ enum monitor_reqtype {

   	MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,

   	MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,

   	MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
@@ -1390,14 +1446,14 @@ 

  +	MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119,

  +	MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121,

  +	MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123,

- +	MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124

-  

-  };

-  

- diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c

- --- openssh-7.6p1/monitor_wrap.c.audit	2017-10-04 17:18:32.750504619 +0200

- +++ openssh-7.6p1/monitor_wrap.c	2017-10-04 17:18:32.838505069 +0200

- @@ -463,7 +463,7 @@ mm_key_allowed(enum mm_keytype type, con

+ +	MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124,

+  

+  	MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151,

+  	MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153,

+ diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c

+ --- openssh/monitor_wrap.c.audit	2019-04-03 17:02:20.653885472 +0200

+ +++ openssh/monitor_wrap.c	2019-04-03 17:02:20.716886069 +0200

+ @@ -513,7 +513,7 @@ mm_key_allowed(enum mm_keytype type, con

    */

   

   int
@@ -1406,7 +1462,7 @@ 

       const u_char *data, size_t datalen, const char *sigalg, u_int compat)

   {

   	struct sshbuf *m;

- @@ -478,7 +478,8 @@ mm_sshkey_verify(const struct sshkey *ke

+ @@ -525,7 +525,8 @@ mm_sshkey_verify(const struct sshkey *ke

   

   	if ((m = sshbuf_new()) == NULL)

   		fatal("%s: sshbuf_new failed", __func__);
@@ -1416,34 +1472,35 @@ 

   	    (r = sshbuf_put_string(m, sig, siglen)) != 0 ||

   	    (r = sshbuf_put_string(m, data, datalen)) != 0 ||

   	    (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0)

- @@ -497,6 +498,20 @@ mm_sshkey_verify(const struct sshkey *ke

+ @@ -547,6 +548,20 @@ mm_sshkey_verify(const struct sshkey *ke

   	return 0;

   }

   

  +int

- +mm_hostbased_key_verify(const struct sshkey *key, const u_char *sig, size_t siglen,

+ +mm_hostbased_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, size_t siglen,

  +    const u_char *data, size_t datalen, const char *pkalg, u_int compat)

  +{

  +	return mm_sshkey_verify(MM_HOSTKEY, key, sig, siglen, data, datalen, pkalg, compat);

  +}

  +

  +int

- +mm_user_key_verify(const struct sshkey *key, const u_char *sig, size_t siglen,

+ +mm_user_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, size_t siglen,

  +    const u_char *data, size_t datalen, const char *pkalg, u_int compat)

  +{

  +	return mm_sshkey_verify(MM_USERKEY, key, sig, siglen, data, datalen, pkalg, compat);

  +}

  +

   void

-  mm_send_keystate(struct monitor *monitor)

+  mm_send_keystate(struct ssh *ssh, struct monitor *monitor)

   {

- @@ -874,11 +889,12 @@ mm_audit_event(ssh_audit_event_t event)

+ @@ -900,11 +915,12 @@ mm_audit_event(struct ssh *ssh, ssh_audi

   	sshbuf_free(m);

   }

   

  -void

+ -mm_audit_run_command(const char *command)

  +int

-  mm_audit_run_command(const char *command)

+ +mm_audit_run_command(struct ssh *ssh, const char *command)

   {

   	struct sshbuf *m;

   	int r;
@@ -1451,7 +1508,7 @@ 

   

   	debug3("%s entering command %s", __func__, command);

   

- @@ -885,6 +901,30 @@ mm_audit_run_command(const char *command

+ @@ -914,6 +930,30 @@ mm_audit_run_command(const char *command

   		fatal("%s: buffer error: %s", __func__, ssh_err(r));

   

   	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m);
@@ -1465,7 +1522,7 @@ 

  +}

  +

  +void

- +mm_audit_end_command(int handle, const char *command)

+ +mm_audit_end_command(struct ssh *ssh, int handle, const char *command)

  +{

  +	int r;

  +	struct sshbuf *m;
@@ -1482,13 +1539,13 @@ 

   	sshbuf_free(m);

   }

   #endif /* SSH_AUDIT_EVENTS */

- @@ -1020,3 +1056,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc

-  	return (ok);

+ @@ -1074,3 +1114,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc

   }

+  

   #endif /* GSSAPI */

  +#ifdef SSH_AUDIT_EVENTS

  +void

- +mm_audit_unsupported_body(int what)

+ +mm_audit_unsupported_body(struct ssh *ssh, int what)

  +{

  +	int r;

  +	struct sshbuf *m;
@@ -1506,7 +1563,7 @@ 

  +}

  +

  +void

- +mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress, char *fps, pid_t pid,

+ +mm_audit_kex_body(struct ssh *ssh, int ctos, char *cipher, char *mac, char *compress, char *fps, pid_t pid,

  +		  uid_t uid)

  +{

  +	int r;
@@ -1531,7 +1588,7 @@ 

  +}

  +

  +void

- +mm_audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)

+ +mm_audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid)

  +{

  +	int r;

  +	struct sshbuf *m;
@@ -1550,7 +1607,7 @@ 

  +}

  +

  +void

- +mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)

+ +mm_audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid)

  +{

  +	int r;

  +	struct sshbuf *m;
@@ -1566,38 +1623,38 @@ 

  +	sshbuf_free(m);

  +}

  +#endif /* SSH_AUDIT_EVENTS */

- diff -up openssh-7.6p1/monitor_wrap.h.audit openssh-7.6p1/monitor_wrap.h

- --- openssh-7.6p1/monitor_wrap.h.audit	2017-10-04 17:18:32.750504619 +0200

- +++ openssh-7.6p1/monitor_wrap.h	2017-10-04 17:18:32.838505069 +0200

- @@ -53,7 +53,9 @@ int mm_key_allowed(enum mm_keytype, cons

+ diff -up openssh/monitor_wrap.h.audit openssh/monitor_wrap.h

+ --- openssh/monitor_wrap.h.audit	2019-04-03 17:02:20.653885472 +0200

+ +++ openssh/monitor_wrap.h	2019-04-03 17:02:20.716886069 +0200

+ @@ -57,7 +57,9 @@ int mm_user_key_allowed(struct ssh *, st

       struct sshauthopt **);

-  int mm_hostbased_key_allowed(struct passwd *, const char *,

+  int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *,

       const char *, struct sshkey *);

  -int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,

- +int mm_hostbased_key_verify(const struct sshkey *, const u_char *, size_t,

+ +int mm_hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t,

  +    const u_char *, size_t, const char *, u_int);

- +int mm_user_key_verify(const struct sshkey *, const u_char *, size_t,

+ +int mm_user_key_verify(struct ssh*, const struct sshkey *, const u_char *, size_t,

       const u_char *, size_t, const char *, u_int);

   

   #ifdef GSSAPI

- @@ -78,7 +80,12 @@ void mm_sshpam_free_ctx(void *);

+ @@ -82,7 +84,12 @@ void mm_sshpam_free_ctx(void *);

   #ifdef SSH_AUDIT_EVENTS

   #include "audit.h"

-  void mm_audit_event(ssh_audit_event_t);

+  void mm_audit_event(struct ssh *, ssh_audit_event_t);

  -void mm_audit_run_command(const char *);

- +int mm_audit_run_command(const char *);

- +void mm_audit_end_command(int, const char *);

- +void mm_audit_unsupported_body(int);

- +void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t);

- +void mm_audit_session_key_free_body(int, pid_t, uid_t);

- +void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t);

+ +int mm_audit_run_command(struct ssh *ssh, const char *);

+ +void mm_audit_end_command(struct ssh *ssh, int, const char *);

+ +void mm_audit_unsupported_body(struct ssh *, int);

+ +void mm_audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t);

+ +void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t);

+ +void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t);

   #endif

   

   struct Session;

- diff -up openssh-7.6p1/packet.c.audit openssh-7.6p1/packet.c

- --- openssh-7.6p1/packet.c.audit	2017-10-04 17:18:32.672504220 +0200

- +++ openssh-7.6p1/packet.c	2017-10-04 17:25:48.141741390 +0200

- @@ -67,6 +67,7 @@

+ diff -up openssh/packet.c.audit openssh/packet.c

+ --- openssh/packet.c.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/packet.c	2019-04-03 17:02:20.716886069 +0200

+ @@ -77,6 +77,7 @@

   #include <zlib.h>

   

   #include "xmalloc.h"
@@ -1605,7 +1662,7 @@ 

   #include "crc32.h"

   #include "compat.h"

   #include "ssh2.h"

- @@ -502,6 +503,13 @@ ssh_packet_get_connection_out(struct ssh

+ @@ -510,6 +511,13 @@ ssh_packet_get_connection_out(struct ssh

   	return ssh->state->connection_out;

   }

   
@@ -1619,7 +1676,7 @@ 

   /*

    * Returns the IP-address of the remote host as a string.  The returned

    * string must not be freed.

- @@ -566,22 +574,19 @@ ssh_packet_close_internal(struct ssh *ss

+ @@ -587,22 +595,19 @@ ssh_packet_close_internal(struct ssh *ss

   {

   	struct session_state *state = ssh->state;

   	u_int mode;
@@ -1642,18 +1699,18 @@ 

  +	state->output = NULL;

   	sshbuf_free(state->outgoing_packet);

  +	state->outgoing_packet = NULL;

- 	sshbuf_free(state->incoming_packet);

+  	sshbuf_free(state->incoming_packet);

  +	state->incoming_packet = NULL;

   	for (mode = 0; mode < MODE_MAX; mode++) {

   		kex_free_newkeys(state->newkeys[mode]);	/* current keys */

   		state->newkeys[mode] = NULL;

- @@ -615,8 +616,18 @@ ssh_packet_close_internal(struct ssh *ss

+ @@ -636,8 +641,18 @@ ssh_packet_close_internal(struct ssh *ss

   	}

   	cipher_free(state->send_context);

   	cipher_free(state->receive_context);

  +	if (had_keys && state->server_side) {

  +		/* Assuming this is called only from privsep child */

- +		audit_session_key_free(MODE_MAX);

+ +		audit_session_key_free(ssh, MODE_MAX);

  +	}

   	state->send_context = state->receive_context = NULL;

   	if (do_close) {
@@ -1666,15 +1723,15 @@ 

   		free(ssh->local_ipaddr);

   		ssh->local_ipaddr = NULL;

   		free(ssh->remote_ipaddr);

- @@ -854,6 +863,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod

-  		   (unsigned long long)state->p_read.blocks,

+ @@ -864,6 +879,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod

   		   (unsigned long long)state->p_send.bytes,

   		   (unsigned long long)state->p_send.blocks);

- +		audit_session_key_free(mode);

-  		cipher_free(*ccp);

-  		*ccp = NULL;

   		kex_free_newkeys(state->newkeys[mode]);

- @@ -2135,6 +2145,72 @@ ssh_packet_get_output(struct ssh *ssh)

+ +		audit_session_key_free(ssh, mode);

+  		state->newkeys[mode] = NULL;

+  	}

+  	/* note that both bytes and the seqnr are not reset */

+ @@ -2167,6 +2183,71 @@ ssh_packet_get_output(struct ssh *ssh)

   	return (void *)ssh->state->output;

   }

   
@@ -1728,18 +1785,17 @@ 

  +}

  +

  +void

- +packet_destroy_all(int audit_it, int privsep)

+ +packet_destroy_all(struct ssh *ssh, int audit_it, int privsep)

  +{

  +	if (audit_it)

- +		audit_it = (active_state != NULL && packet_state_has_keys(active_state->state));

- +	if (active_state != NULL)

- +		packet_destroy_state(active_state->state);

+ +		audit_it = packet_state_has_keys(ssh->state);

+ +	packet_destroy_state(ssh->state);

  +	if (audit_it) {

  +#ifdef SSH_AUDIT_EVENTS

  +		if (privsep)

- +			audit_session_key_free(MODE_MAX);

+ +			audit_session_key_free(ssh, MODE_MAX);

  +		else

- +			audit_session_key_free_body(MODE_MAX, getpid(), getuid());

+ +			audit_session_key_free_body(ssh, MODE_MAX, getpid(), getuid());

  +#endif

  +	}

  +}
@@ -1747,28 +1803,28 @@ 

   /* Reset after_authentication and reset compression in post-auth privsep */

   static int

   ssh_packet_set_postauth(struct ssh *ssh)

- diff -up openssh-7.6p1/packet.h.audit openssh-7.6p1/packet.h

- --- openssh-7.6p1/packet.h.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/packet.h	2017-10-04 17:18:32.838505069 +0200

- @@ -217,4 +217,5 @@ extern struct ssh *active_state;

+ diff -up openssh/packet.h.audit openssh/packet.h

+ --- openssh/packet.h.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/packet.h	2019-04-03 17:02:20.716886069 +0200

+ @@ -217,4 +217,5 @@ const u_char	*sshpkt_ptr(struct ssh *, s

   # undef EC_POINT

   #endif

   

- +void	 packet_destroy_all(int, int);

+ +void	 packet_destroy_all(struct ssh *, int, int);

   #endif				/* PACKET_H */

- diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c

- --- openssh-7.6p1/session.c.audit	2017-10-04 17:18:32.812504936 +0200

- +++ openssh-7.6p1/session.c	2017-10-04 17:18:32.839505074 +0200

- @@ -138,7 +138,7 @@ extern char *__progname;

+ diff -up openssh/session.c.audit openssh/session.c

+ --- openssh/session.c.audit	2019-04-03 17:02:20.712886031 +0200

+ +++ openssh/session.c	2019-04-03 17:02:20.716886069 +0200

+ @@ -136,7 +136,7 @@ extern char *__progname;

   extern int debug_flag;

   extern u_int utmp_len;

   extern int startup_pipe;

  -extern void destroy_sensitive_data(void);

- +extern void destroy_sensitive_data(int);

+ +extern void destroy_sensitive_data(struct ssh *, int);

   extern struct sshbuf *loginmsg;

   extern struct sshauthopt *auth_opts;

-  char *tun_fwd_ifnames; /* serverloop.c */

- @@ -605,6 +605,14 @@ do_exec_pty(struct ssh *ssh, Session *s,

+  extern char *tun_fwd_ifnames; /* serverloop.c */

+ @@ -648,6 +648,14 @@ do_exec_pty(struct ssh *ssh, Session *s,

   	/* Parent.  Close the slave side of the pseudo tty. */

   	close(ttyfd);

   
@@ -1782,8 +1838,8 @@ 

  +

   	/* Enter interactive session. */

   	s->ptymaster = ptymaster;

-  	packet_set_interactive(1, 

- @@ -724,15 +732,19 @@ do_exec(struct ssh *ssh, Session *s, con

+  	ssh_packet_set_interactive(ssh, 1,

+ @@ -740,15 +748,19 @@ do_exec(struct ssh *ssh, Session *s, con

   	    s->self);

   

   #ifdef SSH_AUDIT_EVENTS
@@ -1801,24 +1857,24 @@ 

  +		s->command = xstrdup(shell);

   	}

  +	if (s->command != NULL && s->ptyfd == -1)

- +		s->command_handle = PRIVSEP(audit_run_command(s->command));

+ +		s->command_handle = PRIVSEP(audit_run_command(ssh, s->command));

   #endif

   	if (s->ttyfd != -1)

   		ret = do_exec_pty(ssh, s, command);

- @@ -1499,8 +1511,11 @@ do_child(struct ssh *ssh, Session *s, co

-  	}

+ @@ -1556,8 +1568,11 @@ do_child(struct ssh *ssh, Session *s, co

+  	sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));

   

   	/* remove hostkey from the child's memory */

  -	destroy_sensitive_data();

- +	destroy_sensitive_data(1);

-  	packet_clear_keys();

+ +	destroy_sensitive_data(ssh, 1);

+  	ssh_packet_clear_keys(ssh);

  +	/* Don't audit this - both us and the parent would be talking to the

  +	   monitor over a single socket, with no synchronization. */

- +	packet_destroy_all(0, 1);

+ +	packet_destroy_all(ssh, 0, 1);

   

   	/* Force a password change */

   	if (s->authctxt->force_pwchange) {

- @@ -1714,6 +1729,9 @@ session_unused(int id)

+ @@ -1769,6 +1784,9 @@ session_unused(int id)

   	sessions[id].ttyfd = -1;

   	sessions[id].ptymaster = -1;

   	sessions[id].x11_chanids = NULL;
@@ -1828,7 +1884,7 @@ 

   	sessions[id].next_unused = sessions_first_unused;

   	sessions_first_unused = id;

   }

- @@ -1796,6 +1814,19 @@ session_open(Authctxt *authctxt, int cha

+ @@ -1851,6 +1869,19 @@ session_open(Authctxt *authctxt, int cha

   }

   

   Session *
@@ -1848,17 +1904,17 @@ 

   session_by_tty(char *tty)

   {

   	int i;

- @@ -2307,6 +2338,32 @@ session_exit_message(struct ssh *ssh, Se

+ @@ -2461,6 +2492,32 @@ session_exit_message(struct ssh *ssh, Se

   		chan_write_failed(ssh, c);

   }

   

  +#ifdef SSH_AUDIT_EVENTS

  +void

- +session_end_command2(Session *s)

+ +session_end_command2(struct ssh *ssh, Session *s)

  +{

  +	if (s->command != NULL) {

  +		if (s->command_handle != -1)

- +			audit_end_command(s->command_handle, s->command);

+ +			audit_end_command(ssh, s->command_handle, s->command);

  +		free(s->command);

  +		s->command = NULL;

  +		s->command_handle = -1;
@@ -1866,11 +1922,11 @@ 

  +}

  +

  +static void

- +session_end_command(Session *s)

+ +session_end_command(struct ssh *ssh, Session *s)

  +{

  +	if (s->command != NULL) {

  +		if (s->command_handle != -1)

- +			PRIVSEP(audit_end_command(s->command_handle, s->command));

+ +			PRIVSEP(audit_end_command(ssh, s->command_handle, s->command));

  +		free(s->command);

  +		s->command = NULL;

  +		s->command_handle = -1;
@@ -1881,34 +1937,51 @@ 

   void

   session_close(struct ssh *ssh, Session *s)

   {

- @@ -2320,6 +2377,10 @@ session_close(struct ssh *ssh, Session *

+ @@ -2474,6 +2531,10 @@ session_close(struct ssh *ssh, Session *

   

   	if (s->ttyfd != -1)

   		session_pty_cleanup(s);

  +#ifdef SSH_AUDIT_EVENTS

  +	if (s->command)

- +		session_end_command(s);

+ +		session_end_command(ssh, s);

  +#endif

   	free(s->term);

   	free(s->display);

   	free(s->x11_chanids);

- @@ -2528,6 +2589,15 @@ do_authenticated2(struct ssh *ssh, Authc

+ @@ -2549,14 +2610,14 @@ session_close_by_channel(struct ssh *ssh

+  }

+  

+  void

+ -session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *))

+ +session_destroy_all(struct ssh *ssh, void (*closefunc)(struct ssh *ssh, Session *))

+  {

+  	int i;

+  	for (i = 0; i < sessions_nalloc; i++) {

+  		Session *s = &sessions[i];

+  		if (s->used) {

+  			if (closefunc != NULL)

+ -				closefunc(s);

+ +				closefunc(ssh, s);

+  			else

+  				session_close(ssh, s);

+  		}

+ @@ -2683,6 +2744,15 @@ do_authenticated2(struct ssh *ssh, Authc

   	server_loop2(ssh, authctxt);

   }

   

  +static void

- +do_cleanup_one_session(Session *s)

+ +do_cleanup_one_session(struct ssh *ssh, Session *s)

  +{

  +	session_pty_cleanup2(s);

  +#ifdef SSH_AUDIT_EVENTS

- +	session_end_command2(s);

+ +	session_end_command2(ssh, s);

  +#endif

  +}

  +

   void

   do_cleanup(struct ssh *ssh, Authctxt *authctxt)

   {

- @@ -2585,7 +2655,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au

+ @@ -2746,7 +2816,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au

   	 * or if running in monitor.

   	 */

   	if (!use_privsep || mm_is_monitor())
@@ -1917,10 +1990,10 @@ 

   }

   

   /* Return a name for the remote host that fits inside utmp_size */

- diff -up openssh-7.6p1/session.h.audit openssh-7.6p1/session.h

- --- openssh-7.6p1/session.h.audit	2017-10-02 21:34:26.000000000 +0200

- +++ openssh-7.6p1/session.h	2017-10-04 17:18:32.839505074 +0200

- @@ -60,6 +60,12 @@ struct Session {

+ diff -up openssh/session.h.audit openssh/session.h

+ --- openssh/session.h.audit	2019-03-27 23:26:14.000000000 +0100

+ +++ openssh/session.h	2019-04-03 17:02:20.717886079 +0200

+ @@ -61,6 +61,12 @@ struct Session {

   		char	*name;

   		char	*val;

   	} *env;
@@ -1933,20 +2006,23 @@ 

   };

   

   void	 do_authenticated(struct ssh *, Authctxt *);

- @@ -72,8 +78,10 @@ void	 session_close_by_pid(struct ssh *s

+ @@ -71,10 +77,12 @@ void	 session_unused(int);

+  int	 session_input_channel_req(struct ssh *, Channel *, const char *);

+  void	 session_close_by_pid(struct ssh *ssh, pid_t, int);

   void	 session_close_by_channel(struct ssh *, int, void *);

-  void	 session_destroy_all(struct ssh *, void (*)(Session *));

+ -void	 session_destroy_all(struct ssh *, void (*)(Session *));

+ +void	 session_destroy_all(struct ssh *, void (*)(struct ssh*, Session *));

   void	 session_pty_cleanup2(Session *);

- +void	 session_end_command2(Session *);

+ +void	 session_end_command2(struct ssh *ssh, Session *);

   

   Session	*session_new(void);

  +Session *session_by_id(int);

   Session	*session_by_tty(char *);

   void	 session_close(struct ssh *, Session *);

   void	 do_setusercontext(struct passwd *);

- diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c

- --- openssh-7.6p1/sshd.c.audit	2017-10-04 17:18:32.830505028 +0200

- +++ openssh-7.6p1/sshd.c	2017-10-04 17:18:32.839505074 +0200

+ diff -up openssh/sshd.c.audit openssh/sshd.c

+ --- openssh/sshd.c.audit	2019-04-03 17:02:20.692885842 +0200

+ +++ openssh/sshd.c	2019-04-03 17:02:20.717886079 +0200

  @@ -122,6 +122,7 @@

   #include "ssh-gss.h"

   #endif
@@ -1955,16 +2031,18 @@ 

   #include "ssh-sandbox.h"

   #include "auth-options.h"

   #include "version.h"

- @@ -248,7 +249,7 @@ Buffer loginmsg;

+ @@ -261,8 +262,8 @@ struct sshbuf *loginmsg;

   struct passwd *privsep_pw = NULL;

   

   /* Prototypes for various functions defined later in this file. */

  -void destroy_sensitive_data(void);

- +void destroy_sensitive_data(int);

-  void demote_sensitive_data(void);

-  static void do_ssh2_kex(void);

+ -void demote_sensitive_data(void);

+ +void destroy_sensitive_data(struct ssh *, int);

+ +void demote_sensitive_data(struct ssh *);

+  static void do_ssh2_kex(struct ssh *);

   

- @@ -265,6 +266,15 @@ close_listen_socks(void)

+  /*

+ @@ -278,6 +279,15 @@ close_listen_socks(void)

   	num_listen_socks = -1;

   }

   
@@ -1980,8 +2058,8 @@ 

   static void

   close_startup_pipes(void)

   {

- @@ -475,18 +485,45 @@ sshd_exchange_identification(struct ssh

-  	}

+ @@ -380,18 +390,45 @@ grace_alarm_handler(int sig)

+  	    ssh_remote_port(the_active_state));

   }

   

  -/* Destroy the host and server keys.  They will no longer be needed. */
@@ -1991,7 +2069,7 @@ 

  + */

   void

  -destroy_sensitive_data(void)

- +destroy_sensitive_data(int privsep)

+ +destroy_sensitive_data(struct ssh *ssh, int privsep)

   {

   	u_int i;

  +#ifdef SSH_AUDIT_EVENTS
@@ -2014,10 +2092,10 @@ 

  +			if (fp != NULL) {

  +#ifdef SSH_AUDIT_EVENTS

  +				if (privsep)

- +					PRIVSEP(audit_destroy_sensitive_data(fp,

+ +					PRIVSEP(audit_destroy_sensitive_data(ssh, fp,

  +						pid, uid));

  +				else

- +					audit_destroy_sensitive_data(fp,

+ +					audit_destroy_sensitive_data(ssh, fp,

  +						pid, uid);

  +#endif

  +				free(fp);
@@ -2029,7 +2107,13 @@ 

   			sshkey_free(sensitive_data.host_certificates[i]);

   			sensitive_data.host_certificates[i] = NULL;

   		}

- @@ -499,16 +536,34 @@ demote_sensitive_data(void)

+ @@ -400,14 +437,26 @@ destroy_sensitive_data(void)

+  

+  /* Demote private to public keys for network child */

+  void

+ -demote_sensitive_data(void)

+ +demote_sensitive_data(struct ssh *ssh)

+  {

   	struct sshkey *tmp;

   	u_int i;

   	int r;
@@ -2051,20 +2135,38 @@ 

   			if ((r = sshkey_from_private(

   			    sensitive_data.host_keys[i], &tmp)) != 0)

   				fatal("could not demote host %s key: %s",

-  				    sshkey_type(sensitive_data.host_keys[i]),

+ @@ -415,6 +464,12 @@ demote_sensitive_data(void)

   				    ssh_err(r));

   			sshkey_free(sensitive_data.host_keys[i]);

   			sensitive_data.host_keys[i] = tmp;

  +			if (fp != NULL) {

  +#ifdef SSH_AUDIT_EVENTS

- +				audit_destroy_sensitive_data(fp, pid, uid);

+ +				audit_destroy_sensitive_data(ssh, fp, pid, uid);

  +#endif

  +				free(fp);

  +			}

   		}

   		/* Certs do not need demotion */

   	}

- @@ -587,7 +642,7 @@ privsep_preauth(Authctxt *authctxt)

+ @@ -442,7 +497,7 @@ reseed_prngs(void)

+  }

+  

+  static void

+ -privsep_preauth_child(void)

+ +privsep_preauth_child(struct ssh *ssh)

+  {

+  	gid_t gidset[1];

+  

+ @@ -457,7 +512,7 @@ privsep_preauth_child(void)

+  	reseed_prngs();

+  

+  	/* Demote the private keys to public keys. */

+ -	demote_sensitive_data();

+ +	demote_sensitive_data(ssh);

+  

+  #ifdef WITH_SELINUX

+  	sshd_selinux_change_privsep_preauth_context();

+ @@ -496,7 +551,7 @@ privsep_preauth(struct ssh *ssh)

   

   	if (use_privsep == PRIVSEP_ON)

   		box = ssh_sandbox_init(pmonitor);
@@ -2073,28 +2175,64 @@ 

   	if (pid == -1) {

   		fatal("fork of unprivileged child failed");

   	} else if (pid != 0) {

- @@ -1162,6 +1217,7 @@ server_accept_loop(int *sock_in, int *so

+ @@ -542,7 +597,7 @@ privsep_preauth(struct ssh *ssh)

+  		/* Arrange for logging to be sent to the monitor */

+  		set_log_handler(mm_log_handler, pmonitor);

+  

+ -		privsep_preauth_child();

+ +		privsep_preauth_child(ssh);

+  		setproctitle("%s", "[net]");

+  		if (box != NULL)

+  			ssh_sandbox_child(box);

+ @@ -594,7 +649,7 @@ privsep_postauth(struct ssh *ssh, Authct

+  		set_log_handler(mm_log_handler, pmonitor);

+  

+  	/* Demote the private keys to public keys. */

+ -	demote_sensitive_data();

+ +	demote_sensitive_data(ssh);

+  

+  	reseed_prngs();

+  

+ @@ -1057,7 +1112,7 @@ server_listen(void)

+   * from this function are in a forked subprocess.

+   */

+  static void

+ -server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)

+ +server_accept_loop(struct ssh *ssh, int *sock_in, int *sock_out, int *newsock, int *config_s)

+  {

+  	fd_set *fdset;

+  	int i, j, ret, maxfd;

+ @@ -1112,6 +1167,7 @@ server_accept_loop(int *sock_in, int *so

   		if (received_sigterm) {

   			logit("Received signal %d; terminating.",

   			    (int) received_sigterm);

- +			destroy_sensitive_data(0);

+ +			destroy_sensitive_data(ssh, 0);

   			close_listen_socks();

   			if (options.pid_file != NULL)

   				unlink(options.pid_file);

- @@ -2165,6 +2221,9 @@ main(int ac, char **av)

+ @@ -1978,7 +2034,7 @@ main(int ac, char **av)

+  #endif

+  

+  		/* Accept a connection and return in a forked child */

+ -		server_accept_loop(&sock_in, &sock_out,

+ +		server_accept_loop(ssh, &sock_in, &sock_out,

+  		    &newsock, config_s);

+  	}

+  

+ @@ -2222,6 +2278,9 @@ main(int ac, char **av)

   	do_authenticated(ssh, authctxt);

   

   	/* The connection has been terminated. */

- +	packet_destroy_all(1, 1);

- +	destroy_sensitive_data(1);

+ +	packet_destroy_all(ssh, 1, 1);

+ +	destroy_sensitive_data(ssh, 1);

  +

-  	packet_get_bytes(&ibytes, &obytes);

+  	ssh_packet_get_bytes(ssh, &ibytes, &obytes);

   	verbose("Transferred: sent %llu, received %llu bytes",

   	    (unsigned long long)obytes, (unsigned long long)ibytes);

- @@ -2344,6 +2403,15 @@ void

+ @@ -2401,6 +2460,15 @@ do_ssh2_kex(struct ssh *ssh)

+  void

   cleanup_exit(int i)

   {

-  	struct ssh *ssh = active_state; /* XXX */

  +	static int in_cleanup = 0;

  +	int is_privsep_child;

  +
@@ -2104,29 +2242,31 @@ 

  +	if (in_cleanup)

  +		_exit(i);

  +	in_cleanup = 1;

-  

-  	if (the_authctxt) {

-  		do_cleanup(ssh, the_authctxt);

- @@ -2356,9 +2424,14 @@ cleanup_exit(int i)

+  	if (the_active_state != NULL && the_authctxt != NULL) {

+  		do_cleanup(the_active_state, the_authctxt);

+  		if (use_privsep && privsep_is_preauth &&

+ @@ -2414,9 +2482,16 @@ cleanup_exit(int i)

   				    pmonitor->m_pid, strerror(errno));

   		}

   	}

  +	is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0;

- +	if (sensitive_data.host_keys != NULL)

- +		destroy_sensitive_data(is_privsep_child);

- +	packet_destroy_all(1, is_privsep_child);

+ +	if (sensitive_data.host_keys != NULL && the_active_state != NULL)

+ +		destroy_sensitive_data(the_active_state, is_privsep_child);

+ +	if (the_active_state != NULL)

+ +		packet_destroy_all(the_active_state, 1, is_privsep_child);

   #ifdef SSH_AUDIT_EVENTS

   	/* done after do_cleanup so it can cancel the PAM auth 'thread' */

- -	if (!use_privsep || mm_is_monitor())

- +	if ((the_authctxt == NULL || !the_authctxt->authenticated) &&

+ -	if (the_active_state != NULL && (!use_privsep || mm_is_monitor()))

+ +	if (the_active_state != NULL &&

+ +	    (the_authctxt == NULL || !the_authctxt->authenticated) &&

  +	    (!use_privsep || mm_is_monitor()))

-  		audit_event(SSH_CONNECTION_ABANDON);

+  		audit_event(the_active_state, SSH_CONNECTION_ABANDON);

   #endif

   	_exit(i);

- diff -up openssh-7.6p1/sshkey.c.audit openssh-7.6p1/sshkey.c

- --- openssh-7.6p1/sshkey.c.audit	2017-10-04 17:18:32.758504660 +0200

- +++ openssh-7.6p1/sshkey.c	2017-10-04 17:18:32.839505074 +0200

- @@ -295,6 +295,38 @@ sshkey_type_is_valid_ca(int type)

+ diff -up openssh/sshkey.c.audit openssh/sshkey.c

+ --- openssh/sshkey.c.audit	2019-04-03 17:02:20.657885510 +0200

+ +++ openssh/sshkey.c	2019-04-03 17:02:20.718886088 +0200

+ @@ -331,6 +331,38 @@ sshkey_type_is_valid_ca(int type)

   }

   

   int
@@ -2165,10 +2305,10 @@ 

   sshkey_is_cert(const struct sshkey *k)

   {

   	if (k == NULL)

- diff -up openssh-7.6p1/sshkey.h.audit openssh-7.6p1/sshkey.h

- --- openssh-7.6p1/sshkey.h.audit	2017-10-04 17:18:32.758504660 +0200

- +++ openssh-7.6p1/sshkey.h	2017-10-04 17:18:32.840505079 +0200

- @@ -133,6 +133,7 @@ u_int		 sshkey_size(const struct sshkey

+ diff -up openssh/sshkey.h.audit openssh/sshkey.h

+ --- openssh/sshkey.h.audit	2019-04-03 17:02:20.657885510 +0200

+ +++ openssh/sshkey.h	2019-04-03 17:02:20.718886088 +0200

+ @@ -148,6 +148,7 @@ u_int		 sshkey_size(const struct sshkey

   int		 sshkey_generate(int type, u_int bits, struct sshkey **keyp);

   int		 sshkey_from_private(const struct sshkey *, struct sshkey **);

   int	 sshkey_type_from_name(const char *);

@@ -1,6 +1,6 @@ 

  diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c

- --- openssh/auth2-pubkey.c.refactor	2017-09-27 13:10:19.556830609 +0200

- +++ openssh/auth2-pubkey.c	2017-09-27 13:10:19.677831274 +0200

+ --- openssh/auth2-pubkey.c.refactor	2019-04-04 13:19:12.188821236 +0200

+ +++ openssh/auth2-pubkey.c	2019-04-04 13:19:12.276822078 +0200

  @@ -72,6 +72,9 @@

   extern ServerOptions options;

   extern u_char *session_id2;
@@ -11,7 +11,7 @@ 

   

   static char *

   format_key(const struct sshkey *key)

- @@ -432,7 +435,8 @@ match_principals_command(struct passwd *

+ @@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh

   

   	if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command,

   	    ac, av, &f,
@@ -21,7 +21,7 @@ 

   		goto out;

   

   	uid_swapped = 1;

- @@ -762,7 +766,8 @@ user_key_command_allowed2(struct passwd

+ @@ -981,7 +985,8 @@ user_key_command_allowed2(struct ssh *ss

   

   	if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command,

   	    ac, av, &f,
@@ -32,9 +32,9 @@ 

   

   	uid_swapped = 1;

  diff -up openssh/auth.c.refactor openssh/auth.c

- --- openssh/auth.c.refactor	2017-09-27 13:10:19.640831071 +0200

- +++ openssh/auth.c	2017-09-27 13:10:19.678831279 +0200

- @@ -1435,7 +1435,8 @@ argv_assemble(int argc, char **argv)

+ --- openssh/auth.c.refactor	2019-04-04 13:19:12.235821686 +0200

+ +++ openssh/auth.c	2019-04-04 13:19:12.276822078 +0200

+ @@ -756,7 +756,8 @@ auth_get_canonical_hostname(struct ssh *

    */

   pid_t

   subprocess(const char *tag, struct passwd *pw, const char *command,
@@ -44,7 +44,7 @@ 

   {

   	FILE *f = NULL;

   	struct stat st;

- @@ -1551,7 +1552,7 @@ subprocess(const char *tag, struct passw

+ @@ -872,7 +873,7 @@ subprocess(const char *tag, struct passw

   		}

   

   #ifdef WITH_SELINUX
@@ -54,9 +54,9 @@ 

   			    strerror(errno));

   			_exit(127);

  diff -up openssh/auth.h.refactor openssh/auth.h

- --- openssh/auth.h.refactor	2017-09-25 01:48:10.000000000 +0200

- +++ openssh/auth.h	2017-09-27 13:10:19.678831279 +0200

- @@ -144,7 +144,7 @@ int	 exited_cleanly(pid_t, const char *,

+ --- openssh/auth.h.refactor	2019-04-04 13:19:12.251821839 +0200

+ +++ openssh/auth.h	2019-04-04 13:19:12.276822078 +0200

+ @@ -235,7 +235,7 @@ struct passwd *fakepw(void);

   #define	SSH_SUBPROCESS_STDOUT_CAPTURE  (1<<1)  /* Redirect stdout */

   #define	SSH_SUBPROCESS_STDERR_DISCARD  (1<<2)  /* Discard stderr */

   pid_t	subprocess(const char *, struct passwd *,
@@ -66,8 +66,8 @@ 

   int	 sys_auth_passwd(struct ssh *, const char *);

   

  diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/port-linux.h

- --- openssh/openbsd-compat/port-linux.h.refactor	2017-09-27 13:10:19.634831038 +0200

- +++ openssh/openbsd-compat/port-linux.h	2017-09-27 13:10:54.954025248 +0200

+ --- openssh/openbsd-compat/port-linux.h.refactor	2019-04-04 13:19:12.256821887 +0200

+ +++ openssh/openbsd-compat/port-linux.h	2019-04-04 13:19:12.276822078 +0200

  @@ -26,8 +26,8 @@ void ssh_selinux_setfscreatecon(const ch

   

   int sshd_selinux_enabled(void);
@@ -80,9 +80,9 @@ 

   #endif

   

  diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c

- --- openssh/openbsd-compat/port-linux-sshd.c.refactor	2017-09-27 13:10:19.634831038 +0200

- +++ openssh/openbsd-compat/port-linux-sshd.c	2017-09-27 13:12:06.811420371 +0200

- @@ -48,11 +48,6 @@

+ --- openssh/openbsd-compat/port-linux-sshd.c.refactor	2019-04-04 13:19:12.256821887 +0200

+ +++ openssh/openbsd-compat/port-linux-sshd.c	2019-04-04 13:19:12.276822078 +0200

+ @@ -49,11 +49,6 @@

   #include <unistd.h>

   #endif

   
@@ -94,7 +94,7 @@ 

   /* Wrapper around is_selinux_enabled() to log its return value once only */

   int

   sshd_selinux_enabled(void)

- @@ -222,7 +217,8 @@ get_user_context(const char *sename, con

+ @@ -223,7 +218,8 @@ get_user_context(const char *sename, con

   }

   

   static void
@@ -104,7 +104,7 @@ 

   {

   	*role = NULL;

   	*level = NULL;

- @@ -240,8 +236,8 @@ ssh_selinux_get_role_level(char **role,

+ @@ -241,8 +237,8 @@ ssh_selinux_get_role_level(char **role,

   

   /* Return the default security context for the given username */

   static int
@@ -115,7 +115,7 @@ 

   {

   	char *sename, *lvl;

   	char *role;

- @@ -249,7 +245,7 @@ sshd_selinux_getctxbyname(char *pwname,

+ @@ -250,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname,

   	int r = 0;

   	context_t con = NULL;

   
@@ -124,7 +124,7 @@ 

   

   #ifdef HAVE_GETSEUSERBYNAME

   	if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {

- @@ -271,7 +267,7 @@ sshd_selinux_getctxbyname(char *pwname,

+ @@ -272,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname,

   

   	if (r == 0) {

   		/* If launched from xinetd, we must use current level */
@@ -133,7 +133,7 @@ 

   			security_context_t sshdsc=NULL;

   

   			if (getcon_raw(&sshdsc) < 0)

- @@ -332,7 +328,8 @@ sshd_selinux_getctxbyname(char *pwname,

+ @@ -333,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname,

   

   /* Setup environment variables for pam_selinux */

   static int
@@ -143,7 +143,7 @@ 

   {

   	const char *reqlvl;

   	char *role;

- @@ -341,11 +338,11 @@ sshd_selinux_setup_variables(int(*set_it

+ @@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it

   

   	debug3("%s: setting execution context", __func__);

   
@@ -157,7 +157,7 @@ 

   		use_current = "1";

   	} else {

   		use_current = "";

- @@ -361,9 +358,10 @@ sshd_selinux_setup_variables(int(*set_it

+ @@ -362,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it

   }

   

   static int
@@ -170,7 +170,7 @@ 

   }

   

   static int

- @@ -373,25 +371,28 @@ do_setenv(char *name, const char *value)

+ @@ -374,25 +372,28 @@ do_setenv(char *name, const char *value)

   }

   

   int
@@ -204,7 +204,7 @@ 

   			switch (security_getenforce()) {

   			case -1:

   				fatal("%s: security_getenforce() failed", __func__);

- @@ -409,7 +410,7 @@ sshd_selinux_setup_exec_context(char *pw

+ @@ -410,7 +411,7 @@ sshd_selinux_setup_exec_context(char *pw

   

   	debug3("%s: setting execution context", __func__);

   
@@ -214,9 +214,9 @@ 

   		r = setexeccon(user_ctx);

   		if (r < 0) {

  diff -up openssh/platform.c.refactor openssh/platform.c

- --- openssh/platform.c.refactor	2017-09-27 13:10:19.574830708 +0200

- +++ openssh/platform.c	2017-09-27 13:11:45.475303050 +0200

- @@ -33,6 +33,9 @@

+ --- openssh/platform.c.refactor	2019-04-04 13:19:12.204821389 +0200

+ +++ openssh/platform.c	2019-04-04 13:19:12.277822088 +0200

+ @@ -32,6 +32,9 @@

   

   extern int use_privsep;

   extern ServerOptions options;
@@ -226,7 +226,7 @@ 

   

   void

   platform_pre_listen(void)

- @@ -184,7 +187,9 @@ platform_setusercontext_post_groups(stru

+ @@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru

   	}

   #endif /* HAVE_SETPCRED */

   #ifdef WITH_SELINUX
@@ -238,9 +238,27 @@ 

   }

   

  diff -up openssh/sshd.c.refactor openssh/sshd.c

- --- openssh/sshd.c.refactor	2017-09-27 13:10:19.674831257 +0200

- +++ openssh/sshd.c	2017-09-27 13:12:01.635391909 +0200

- @@ -2135,7 +2135,9 @@ main(int ac, char **av)

+ --- openssh/sshd.c.refactor	2019-04-04 13:19:12.275822068 +0200

+ +++ openssh/sshd.c	2019-04-04 13:19:51.270195262 +0200

+ @@ -158,7 +158,7 @@ int debug_flag = 0;

+  static int test_flag = 0;

+  

+  /* Flag indicating that the daemon is being started from inetd. */

+ -static int inetd_flag = 0;

+ +int inetd_flag = 0;

+  

+  /* Flag indicating that sshd should not detach and become a daemon. */

+  static int no_daemon_flag = 0;

+ @@ -171,7 +171,7 @@ static char **saved_argv;

+  static int saved_argc;

+  

+  /* re-exec */

+ -static int rexeced_flag = 0;

+ +int rexeced_flag = 0;

+  static int rexec_flag = 1;

+  static int rexec_argc = 0;

+  static char **rexec_argv;

+ @@ -2192,7 +2192,9 @@ main(int ac, char **av)

   	}

   #endif

   #ifdef WITH_SELINUX

@@ -1,794 +0,0 @@ 

- diff -up openssh/ssh-pkcs11-client.c.pkcs11-ecdsa openssh/ssh-pkcs11-client.c

- --- openssh/ssh-pkcs11-client.c.pkcs11-ecdsa	2018-10-12 14:05:55.020656974 +0200

- +++ openssh/ssh-pkcs11-client.c	2018-10-12 14:05:55.023656999 +0200

- @@ -31,6 +31,15 @@

-  #include <errno.h>

-  

-  #include <openssl/rsa.h>

- +#ifdef OPENSSL_HAS_ECC

- +#include <openssl/ecdsa.h>

- +#if ((defined(LIBRESSL_VERSION_NUMBER) && \

- +	(LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \

- +	(defined(ECDSA_F_ECDSA_METHOD_NEW)) || \

- +	(OPENSSL_VERSION_NUMBER >= 0x00010100L)

- +#define ENABLE_PKCS11_ECDSA 1

- +#endif

- +#endif

-  

-  #include "openbsd-compat/openssl-compat.h"

-  

- @@ -155,9 +164,9 @@ pkcs11_rsa_private_encrypt(int flen, con

-  	return (ret);

-  }

-  

- -/* redirect the private key encrypt operation to the ssh-pkcs11-helper */

- +/* redirect the RSA private key encrypt operation to the ssh-pkcs11-helper */

-  static int

- -wrap_key(RSA *rsa)

- +wrap_rsa_key(RSA *rsa)

-  {

-  	static RSA_METHOD *helper_rsa;

-  

- @@ -170,6 +179,88 @@ wrap_key(RSA *rsa)

-  	return (0);

-  }

-  

- +#ifdef ENABLE_PKCS11_ECDSA

- +static ECDSA_SIG *

- +pkcs11_ecdsa_private_sign(const unsigned char *from, int flen,

- +    const BIGNUM *inv, const BIGNUM *rp, EC_KEY * ecdsa)

- +{

- +	struct sshkey *key = NULL;

- +	u_char *blob, *signature = NULL;

- +	size_t blen, slen = 0;

- +	struct sshbuf *msg = NULL;

- +	ECDSA_SIG *ret = NULL;

- +	BIGNUM *r = NULL, *s = NULL;

- +	int rv;

- +

- +	if ((key = sshkey_new(KEY_ECDSA)) == NULL)

- +		fatal("%s: sshkey_new failed", __func__);

- +	key->ecdsa = ecdsa;

- +	key->ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa);

- +	if (sshkey_to_blob(key, &blob, &blen) == 0)

- +		goto out;

- +	if ((msg = sshbuf_new()) == NULL)

- +		fatal("%s: sshbuf_new failed", __func__);

- +	if ((rv = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||

- +	    (rv = sshbuf_put_string(msg, blob, blen)) != 0 ||

- +	    (rv = sshbuf_put_string(msg, from, flen)) != 0 ||

- +	    (rv = sshbuf_put_u32(msg, 0)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(rv));

- +	free(blob);

- +	send_msg(msg);

- +	sshbuf_reset(msg);

- +

- +	if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {

- +		if ((rv = sshbuf_get_string(msg, &signature, &slen)) != 0)

- +			fatal("%s: buffer error: %s", __func__, ssh_err(rv));

- +		if (slen <= (size_t)ECDSA_size(ecdsa)) {

- +			int nlen = slen / 2;

- +			ret = ECDSA_SIG_new();

- +			r = BN_new();

- +			s = BN_new();

- +			BN_bin2bn(&signature[0], nlen, r);

- +			BN_bin2bn(&signature[nlen], nlen, s);

- +			ECDSA_SIG_set0(ret, r, s);

- +		}

- +		free(signature);

- +	}

- +out:

- +	sshkey_free(key);

- +	sshbuf_free(msg);

- +	return (ret);

- +}

- +

- +/* redirect the ECDSA private key encrypt operation to the ssh-pkcs11-helper */

- +static int

- +wrap_ecdsa_key(EC_KEY *ecdsa) {

- +#if (OPENSSL_VERSION_NUMBER >= 0x00010100L)

- +	static EC_KEY_METHOD *helper_ecdsa = NULL;

- +	if (helper_ecdsa == NULL) {

- +		const EC_KEY_METHOD *def = EC_KEY_get_default_method();

- +		helper_ecdsa = EC_KEY_METHOD_new(def);

- +		EC_KEY_METHOD_set_sign(helper_ecdsa, NULL, NULL, pkcs11_ecdsa_private_sign);

- +	}

- +	EC_KEY_set_method(ecdsa, helper_ecdsa);

- +#else

- +	static ECDSA_METHOD *helper_ecdsa = NULL;

- +	if(helper_ecdsa == NULL) {

- +		const ECDSA_METHOD *def = ECDSA_get_default_method();

- +# ifdef ECDSA_F_ECDSA_METHOD_NEW

- +		helper_ecdsa = ECDSA_METHOD_new((ECDSA_METHOD *)def);

- +		ECDSA_METHOD_set_name(helper_ecdsa, "ssh-pkcs11-helper-ecdsa");

- +		ECDSA_METHOD_set_sign(helper_ecdsa, pkcs11_ecdsa_private_sign);

- +# else

- +		helper_ecdsa = xcalloc(1, sizeof(*helper_ecdsa));

- +		memcpy(helper_ecdsa, def, sizeof(*helper_ecdsa));

- +		helper_ecdsa->name = "ssh-pkcs11-helper-ecdsa";

- +		helper_ecdsa->ecdsa_do_sign = pkcs11_ecdsa_private_sign;

- +# endif

- +	}

- +	ECDSA_set_method(ecdsa, helper_ecdsa);

- +#endif

- +	return (0);

- +}

- +#endif

- +

-  static int

-  pkcs11_start_helper(void)

-  {

- @@ -238,7 +329,15 @@ pkcs11_add_provider(char *name, char *pi

-  				    __func__, ssh_err(r));

-  			if ((r = sshkey_from_blob(blob, blen, &k)) != 0)

-  				fatal("%s: bad key: %s", __func__, ssh_err(r));

- -			wrap_key(k->rsa);

- +			if(k->type == KEY_RSA) {

- +				wrap_rsa_key(k->rsa);

- +#ifdef ENABLE_PKCS11_ECDSA

- +			} else if(k->type == KEY_ECDSA) {

- +				wrap_ecdsa_key(k->ecdsa);

- +#endif /* ENABLE_PKCS11_ECDSA */

- +			} else {

- +				/* Unsupported type */

- +			}

-  			(*keysp)[i] = k;

-  			free(blob);

-  		}

- diff -up openssh/ssh-pkcs11.c.pkcs11-ecdsa openssh/ssh-pkcs11.c

- --- openssh/ssh-pkcs11.c.pkcs11-ecdsa	2018-10-12 14:05:55.021656982 +0200

- +++ openssh/ssh-pkcs11.c	2018-10-12 14:11:54.292636679 +0200

- @@ -33,6 +33,16 @@

-  #include "openbsd-compat/openssl-compat.h"

-  

-  #include <openssl/x509.h>

- +#include <openssl/rsa.h>

- +#ifdef OPENSSL_HAS_ECC

- +#include <openssl/ecdsa.h>

- +#if ((defined(LIBRESSL_VERSION_NUMBER) && \

- +	(LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \

- +	(defined(ECDSA_F_ECDSA_METHOD_NEW)) || \

- +	(OPENSSL_VERSION_NUMBER >= 0x00010100L)

- +#define ENABLE_PKCS11_ECDSA 1

- +#endif

- +#endif

-  

-  #define CRYPTOKI_COMPAT

-  #include "pkcs11.h"

- @@ -74,6 +84,7 @@ TAILQ_HEAD(, pkcs11_provider) pkcs11_pro

-  struct pkcs11_key {

-  	struct pkcs11_provider	*provider;

-  	CK_ULONG		slotidx;

- +	CK_ULONG		key_type;

-  	int			(*orig_finish)(RSA *rsa);

-  	RSA_METHOD		*rsa_method;

-  	char			*keyid;

- @@ -82,6 +93,9 @@ struct pkcs11_key {

-  };

-  

-  int pkcs11_interactive = 0;

- +#ifdef ENABLE_PKCS11_ECDSA

- +static int pkcs11_key_idx = -1;

- +#endif /* ENABLE_PKCS11_ECDSA */

-  

-  /*

-   * This can't be in the ssh-pkcs11-uri, becase we can not depend on

- @@ -345,6 +359,40 @@ pkcs11_find(struct pkcs11_provider *p, C

-  	return (ret);

-  }

-  

- +int pkcs11_login(struct pkcs11_key *k11, CK_FUNCTION_LIST *f, struct pkcs11_slotinfo *si) {

- +	char			*pin = NULL, prompt[1024];

- +	CK_RV			rv;

- +	if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {

- +		if (!pkcs11_interactive) {

- +			error("need pin entry%s", (si->token.flags &

- +			    CKF_PROTECTED_AUTHENTICATION_PATH) ?

- +			    " on reader keypad" : "");

- +			return (-1);

- +		}

- +		if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)

- +			verbose("Deferring PIN entry to reader keypad.");

- +		else {

- +			snprintf(prompt, sizeof(prompt),

- +			    "Enter PIN for '%s': ", si->token.label);

- +			pin = read_passphrase(prompt, RP_ALLOW_EOF);

- +			if (pin == NULL)

- +				return (-1);	/* bail out */

- +		}

- +		rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,

- +		    (pin != NULL) ? strlen(pin) : 0);

- +		if (pin != NULL) {

- +			explicit_bzero(pin, strlen(pin));

- +			free(pin);

- +		}

- +		if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {

- +			error("C_Login failed: %lu", rv);

- +			return (-1);

- +		}

- +		si->logged_in = 1;

- +	}

- +	return 0;

- +}

- +

-  /* openssl callback doing the actual signing operation */

-  static int

-  pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,

- @@ -366,7 +414,6 @@ pkcs11_rsa_private_encrypt(int flen, con

-  		{CKA_ID, NULL, 0},

-  		{CKA_SIGN, NULL, sizeof(true_val) }

-  	};

- -	char			*pin = NULL, prompt[1024];

-  	int			rval = -1;

-  

-  	key_filter[0].pValue = &private_key_class;

- @@ -383,33 +430,8 @@ pkcs11_rsa_private_encrypt(int flen, con

-  	}

-  	f = k11->provider->module->function_list;

-  	si = &k11->provider->module->slotinfo[k11->slotidx];

- -	if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {

- -		if (!pkcs11_interactive) {

- -			error("need pin entry%s", (si->token.flags &

- -			    CKF_PROTECTED_AUTHENTICATION_PATH) ?

- -			    " on reader keypad" : "");

- -			return (-1);

- -		}

- -		if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)

- -			verbose("Deferring PIN entry to reader keypad.");

- -		else {

- -			snprintf(prompt, sizeof(prompt),

- -			    "Enter PIN for '%s': ", si->token.label);

- -			pin = read_passphrase(prompt, RP_ALLOW_EOF);

- -			if (pin == NULL)

- -				return (-1);	/* bail out */

- -		}

- -		rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,

- -		    (pin != NULL) ? strlen(pin) : 0);

- -		if (pin != NULL) {

- -			explicit_bzero(pin, strlen(pin));

- -			free(pin);

- -		}

- -		if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {

- -			error("C_Login failed: %lu", rv);

- -			return (-1);

- -		}

- -		si->logged_in = 1;

- +	if(pkcs11_login(k11, f, si)) {

- +		return (-1);

-  	}

-  	key_filter[1].pValue = k11->keyid;

-  	key_filter[1].ulValueLen = k11->keyid_len;

- @@ -447,6 +469,7 @@ pkcs11_rsa_wrap(struct pkcs11_provider *

-  	const RSA_METHOD	*def = RSA_get_default_method();

-  

-  	k11 = xcalloc(1, sizeof(*k11));

- +	k11->key_type = CKK_RSA;

-  	k11->provider = provider;

-  	provider->refcount++;	/* provider referenced by RSA key */

-  	k11->slotidx = slotidx;

- @@ -477,6 +500,184 @@ pkcs11_rsa_wrap(struct pkcs11_provider *

-  	return (0);

-  }

-  

- +#ifdef ENABLE_PKCS11_ECDSA

- +static ECDSA_SIG *pkcs11_ecdsa_sign(const unsigned char *dgst, int dgst_len,

- +                                    const BIGNUM *inv, const BIGNUM *rp,

- +                                    EC_KEY *ecdsa) {

- +	struct pkcs11_key	*k11;

- +	struct pkcs11_slotinfo	*si;

- +	CK_FUNCTION_LIST	*f;

- +	CK_OBJECT_HANDLE	obj;

- +	CK_ULONG		tlen = 0;

- +	CK_RV			rv;

- +	CK_OBJECT_CLASS	private_key_class = CKO_PRIVATE_KEY;

- +	CK_BBOOL		true_val = CK_TRUE;

- +	CK_MECHANISM		mech = {

- +		CKM_ECDSA, NULL_PTR, 0

- +	};

- +	CK_ATTRIBUTE		key_filter[] = {

- +		{CKA_CLASS, NULL, sizeof(private_key_class) },

- +		{CKA_ID, NULL, 0},

- +		{CKA_SIGN, NULL, sizeof(true_val) }

- +	};

- +	ECDSA_SIG  		*rval = NULL;

- +	key_filter[0].pValue = &private_key_class;

- +	key_filter[2].pValue = &true_val;

- +

- + #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)

- +	if ((k11 = (struct pkcs11_key *)EC_KEY_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) {

- +		error("EC_KEY_get_ex_data failed for ecdsa %p", ecdsa);

- + #else

- +	if ((k11 = (struct pkcs11_key *)ECDSA_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) {

- +		error("ECDSA_get_ex_data failed for ecdsa %p", ecdsa);

- + #endif

- +		return NULL;

- +	}

- +	if (!k11->provider || !k11->provider->valid) {

- +		error("no pkcs11 (valid) provider for ecdsa %p", ecdsa);

- +		return NULL;

- +	}

- +	f = k11->provider->module->function_list;

- +	si = &k11->provider->module->slotinfo[k11->slotidx];

- +	if(pkcs11_login(k11, f, si)) {

- +		return NULL;

- +	}

- +	key_filter[1].pValue = k11->keyid;

- +	key_filter[1].ulValueLen = k11->keyid_len;

- +	/* try to find object w/CKA_SIGN first, retry w/o */

- +	if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&

- +	    pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {

- +		error("cannot find private key");

- +	} else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {

- +		error("C_SignInit failed: %lu", rv);

- +	} else {

- +		CK_BYTE_PTR buf = NULL;

- +		BIGNUM *r = NULL, *s = NULL;

- +		int nlen;

- +		/* Make a call to C_Sign to find out the size of the signature */

- +		rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, NULL, &tlen);

- +		if (rv != CKR_OK) {

- +			error("C_Sign failed: %lu", rv);

- +			return NULL;

- +		}

- +		if ((buf = xmalloc(tlen)) == NULL) {

- +			error("failure to allocate signature buffer");

- +			return NULL;

- +		}

- +		rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, buf, &tlen);

- +		if (rv != CKR_OK) {

- +			error("C_Sign failed: %lu", rv);

- +		}

- +

- +		if ((rval = ECDSA_SIG_new()) == NULL ||

- +		    (r = BN_new()) == NULL ||

- +		    (s = BN_new()) == NULL) {

- +			error("failure to allocate ECDSA signature");

- +		} else {

- +			/*

- +			 * ECDSA signature is 2 large integers of same size returned

- +			 * concatenated by PKCS#11, we separate them to create an

- +			 * ECDSA_SIG for OpenSSL.

- +			 */

- +			nlen = tlen / 2;

- +			BN_bin2bn(&buf[0], nlen, r);

- +			BN_bin2bn(&buf[nlen], nlen, s);

- +			ECDSA_SIG_set0(rval, r, s);

- +		}

- +		free(buf);

- +	}

- +	return (rval);

- +}

- +

- +#if (OPENSSL_VERSION_NUMBER >= 0x00010100L)

- +static EC_KEY_METHOD *get_pkcs11_ecdsa_method(void) {

- +	static EC_KEY_METHOD *pkcs11_ecdsa_method = NULL;

- +	if(pkcs11_key_idx == -1) {

- +		pkcs11_key_idx = EC_KEY_get_ex_new_index(0, NULL, NULL, NULL, 0);

- +	}

- +	if (pkcs11_ecdsa_method == NULL) {

- +		const EC_KEY_METHOD *def = EC_KEY_get_default_method();

- +		pkcs11_ecdsa_method = EC_KEY_METHOD_new(def);

- +		EC_KEY_METHOD_set_sign(pkcs11_ecdsa_method, NULL, NULL, pkcs11_ecdsa_sign);

- +	}

- +#else

- +static ECDSA_METHOD *get_pkcs11_ecdsa_method(void) {

- +	static ECDSA_METHOD *pkcs11_ecdsa_method = NULL;

- +	if(pkcs11_key_idx == -1) {

- +		pkcs11_key_idx = ECDSA_get_ex_new_index(0, NULL, NULL, NULL, 0);

- +	}

- +	if(pkcs11_ecdsa_method == NULL) {

- +		const ECDSA_METHOD *def = ECDSA_get_default_method();

- + #ifdef ECDSA_F_ECDSA_METHOD_NEW

- +		pkcs11_ecdsa_method = ECDSA_METHOD_new((ECDSA_METHOD *)def);

- +		ECDSA_METHOD_set_name(pkcs11_ecdsa_method, "pkcs11");

- +		ECDSA_METHOD_set_sign(pkcs11_ecdsa_method, pkcs11_ecdsa_sign);

- + #else

- +		pkcs11_ecdsa_method = xcalloc(1, sizeof(*pkcs11_ecdsa_method));

- +		memcpy(pkcs11_ecdsa_method, def, sizeof(*pkcs11_ecdsa_method));

- +		pkcs11_ecdsa_method->name = "pkcs11";

- +		pkcs11_ecdsa_method->ecdsa_do_sign = pkcs11_ecdsa_sign;

- + #endif

- +	}

- +#endif

- +	return pkcs11_ecdsa_method;

- +}

- +

- +static int

- +pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,

- +                  CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ecdsa)

- +{

- +	struct pkcs11_key *k11;

- +	k11 = xcalloc(1, sizeof(*k11));

- +	k11->key_type = CKK_EC;

- +	k11->provider = provider;

- +	provider->refcount++; /* provider referenced by ECDSA key */

- +	k11->slotidx = slotidx;

- +	/* identify key object on smartcard */

- +	k11->keyid_len = keyid_attrib->ulValueLen;

- +	if (k11->keyid_len > 0) {

- +		k11->keyid = xmalloc(k11->keyid_len);

- +		memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);

- +	}

- +	if (label_attrib->ulValueLen > 0 ) {

- +		k11->label = xmalloc(label_attrib->ulValueLen+1);

- +		memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen);

- +		k11->label[label_attrib->ulValueLen] = 0;

- +	}

- + #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)

- +	EC_KEY_set_method(ecdsa, get_pkcs11_ecdsa_method());

- +	EC_KEY_set_ex_data(ecdsa, pkcs11_key_idx, k11);

- + #else

- +	ECDSA_set_method(ecdsa, get_pkcs11_ecdsa_method());

- +	ECDSA_set_ex_data(ecdsa, pkcs11_key_idx, k11);

- + #endif

- +	return (0);

- +}

- +#endif /* ENABLE_PKCS11_ECDSA */

- +

- +int pkcs11_del_key(struct sshkey *key) {

- +#ifdef ENABLE_PKCS11_ECDSA

- +	if(key->type == KEY_ECDSA) {

- +		struct pkcs11_key *k11 = (struct pkcs11_key *)

- + #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)

- +			EC_KEY_get_ex_data(key->ecdsa, pkcs11_key_idx);

- + #else

- +			ECDSA_get_ex_data(key->ecdsa, pkcs11_key_idx);

- + #endif

- +		if (k11 == NULL) {

- +			error("EC_KEY_get_ex_data failed for ecdsa %p", key->ecdsa);

- +		} else {

- +			if (k11->provider)

- +				pkcs11_provider_unref(k11->provider);

- +			free(k11->keyid);

- +			free(k11);

- +		}

- +	}

- +#endif /* ENABLE_PKCS11_ECDSA */

- +	sshkey_free(key);

- +	return (0);

- +}

- +

-  /* remove trailing spaces */

-  static void

-  rmspace(u_char *buf, size_t len)

- @@ -544,11 +745,13 @@ static int

-  pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,

-      struct sshkey ***keysp, int *nkeys, struct pkcs11_uri *uri)

-  {

- -	size_t filter_size = 1;

- +	size_t filter_size = 2;

- +	CK_KEY_TYPE pubkey_type = CKK_RSA;

-  	CK_OBJECT_CLASS	pubkey_class = CKO_PUBLIC_KEY;

-  	CK_OBJECT_CLASS	cert_class = CKO_CERTIFICATE;

-  	CK_ATTRIBUTE		pubkey_filter[] = {

-  		{ CKA_CLASS, NULL, sizeof(pubkey_class) },

- +		{ CKA_KEY_TYPE, NULL, sizeof(pubkey_type) },

-  		{ CKA_ID, NULL, 0 },

-  		{ CKA_LABEL, NULL, 0 }

-  	};

- @@ -569,37 +772,72 @@ pkcs11_fetch_keys(struct pkcs11_provider

-  		{ CKA_SUBJECT, NULL, 0 },

-  		{ CKA_VALUE, NULL, 0 }

-  	};

- +#ifdef ENABLE_PKCS11_ECDSA

- +	CK_KEY_TYPE	        ecdsa_type = CKK_EC;

- +	CK_ATTRIBUTE		ecdsa_filter[] = {

- +		{ CKA_CLASS, NULL, sizeof(pubkey_class) },

- +		{ CKA_KEY_TYPE, NULL, sizeof(ecdsa_type) },

- +		{ CKA_ID, NULL, 0 },

- +		{ CKA_LABEL, NULL, 0 }

- +	};

- +	CK_ATTRIBUTE		ecdsa_attribs[] = {

- +		{ CKA_ID, NULL, 0 },

- +		{ CKA_LABEL, NULL, 0 },

- +		{ CKA_EC_PARAMS, NULL, 0 },

- +		{ CKA_EC_POINT, NULL, 0 }

- +	};

- +	ecdsa_filter[0].pValue = &pubkey_class;

- +	ecdsa_filter[1].pValue = &ecdsa_type;

- +#endif /* ENABLE_PKCS11_ECDSA */

-  	pubkey_filter[0].pValue = &pubkey_class;

- +	pubkey_filter[1].pValue = &pubkey_type;

-  	cert_filter[0].pValue = &cert_class;

-  

-  	if (uri->id != NULL) {

-  		pubkey_filter[filter_size].pValue = uri->id;

-  		pubkey_filter[filter_size].ulValueLen = uri->id_len;

- -		cert_filter[filter_size].pValue = uri->id;

- -		cert_filter[filter_size].ulValueLen = uri->id_len;

- +#ifdef ENABLE_PKCS11_ECDSA

- +		ecdsa_filter[filter_size].pValue = uri->id;

- +		ecdsa_filter[filter_size].ulValueLen = uri->id_len;

- +#endif /* ENABLE_PKCS11_ECDSA */

- +		cert_filter[filter_size-1].pValue = uri->id;

- +		cert_filter[filter_size-1].ulValueLen = uri->id_len;

-  		filter_size++;

-  	}

-  	if (uri->object != NULL) {

-  		pubkey_filter[filter_size].pValue = uri->object;

-  		pubkey_filter[filter_size].ulValueLen = strlen(uri->object);

-  		pubkey_filter[filter_size].type = CKA_LABEL;

- -		cert_filter[filter_size].pValue = uri->object;

- -		cert_filter[filter_size].ulValueLen = strlen(uri->object);

- -		cert_filter[filter_size].type = CKA_LABEL;

- +#ifdef ENABLE_PKCS11_ECDSA

- +		ecdsa_filter[filter_size].pValue = uri->object;

- +		ecdsa_filter[filter_size].ulValueLen = strlen(uri->object);

- +		ecdsa_filter[filter_size].type = CKA_LABEL;

- +#endif /* ENABLE_PKCS11_ECDSA */

- +		cert_filter[filter_size-1].pValue = uri->object;

- +		cert_filter[filter_size-1].ulValueLen = strlen(uri->object);

- +		cert_filter[filter_size-1].type = CKA_LABEL;

-  		filter_size++;

-  	}

-  

-  	if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, filter_size,

-  	    pubkey_attribs, keysp, nkeys) < 0 ||

- -	    pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size,

- +#ifdef ENABLE_PKCS11_ECDSA

- +	    pkcs11_fetch_keys_filter(p, slotidx, ecdsa_filter, filter_size,

- +	    ecdsa_attribs, keysp, nkeys) < 0||

- +#endif /* ENABLE_PKCS11_ECDSA */

- +	    pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size - 1,

-  	    cert_attribs, keysp, nkeys) < 0)

-  		return (-1);

-  	if (*nkeys == 0) {

-  		/* Try once more without the label filter */

-  		filter_size--;

-  		if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, filter_size,

-  		    pubkey_attribs, keysp, nkeys) < 0 ||

- -		    pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size,

- +#ifdef ENABLE_PKCS11_ECDSA

- +		    pkcs11_fetch_keys_filter(p, slotidx, ecdsa_filter, filter_size,

- +		    ecdsa_attribs, keysp, nkeys) < 0||

- +#endif /* ENABLE_PKCS11_ECDSA */

- +		    pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size - 1,

-  		    cert_attribs, keysp, nkeys) < 0)

-  	 		return (-1);

-  	}

- @@ -624,8 +858,13 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-      CK_ATTRIBUTE filter[], size_t filter_size, CK_ATTRIBUTE attribs[4],

-      struct sshkey ***keysp, int *nkeys)

-  {

- -	struct sshkey		*key;

- +	struct sshkey		*key = NULL;

-  	RSA			*rsa;

- +#ifdef ENABLE_PKCS11_ECDSA

- +	EC_KEY			*ecdsa;

- +#else

- +	void			*ecdsa;

- +#endif /* ENABLE_PKCS11_ECDSA */

-  	X509 			*x509;

-  	EVP_PKEY		*evp = NULL;

-  	int			i;

- @@ -678,6 +917,9 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  		 * or ID, label, subject and value for certificates.

-  		 */

-  		rsa = NULL;

- +#ifdef ENABLE_PKCS11_ECDSA

- +		ecdsa = NULL;

- +#endif /* ENABLE_PKCS11_ECDSA */

-  		if ((rv = f->C_GetAttributeValue(session, obj, attribs, nattribs))

-  		    != CKR_OK) {

-  			error("C_GetAttributeValue failed: %lu", rv);

- @@ -700,6 +942,45 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  				BN_free(rsa_n);

-  				BN_free(rsa_e);

-  			}

- +#ifdef ENABLE_PKCS11_ECDSA

- +		} else if (attribs[2].type == CKA_EC_PARAMS ) {

- +			if ((ecdsa = EC_KEY_new()) == NULL) {

- +				error("EC_KEY_new failed");

- +			} else {

- +				const unsigned char *ptr1 = attribs[2].pValue;

- +				const unsigned char *ptr2 = attribs[3].pValue;

- +				CK_ULONG len1 = attribs[2].ulValueLen;

- +				CK_ULONG len2 = attribs[3].ulValueLen;

- +				ASN1_OCTET_STRING *point = NULL;

- +

- +				/*

- +				 * CKA_EC_PARAMS contains the curve parameters of the key

- +				 * either referenced as an OID or directly with all values.

- +				 * CKA_EC_POINT contains the point (public key) on the curve.

- +				 * The point is should be returned inside a DER-encoded

- +				 * ASN.1 OCTET STRING value (but some implementation).

- +				 */

- +				if ((point = d2i_ASN1_OCTET_STRING(NULL, &ptr2, len2))) {

- +					/* Pointing to OCTET STRING content */

- +					ptr2 = point->data;

- +					len2 = point->length;

- +				} else {

- +					/* No OCTET STRING */

- +					ptr2 = attribs[3].pValue;

- +				}

- +

- +				if((d2i_ECParameters(&ecdsa, &ptr1, len1) == NULL) ||

- +				   (o2i_ECPublicKey(&ecdsa, &ptr2, len2) == NULL)) {

- +					EC_KEY_free(ecdsa);

- +					ecdsa = NULL;

- +					error("EC public key parsing failed");

- +				}

- +

- +				if(point) {

- +					ASN1_OCTET_STRING_free(point);

- +				}

- +			}

- +#endif /* ENABLE_PKCS11_ECDSA */

-  		} else {

-  			cp = attribs[3].pValue;

-  			if ((x509 = X509_new()) == NULL) {

- @@ -707,13 +988,28 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  			} else if (d2i_X509(&x509, &cp, attribs[3].ulValueLen)

-  			    == NULL) {

-  				error("d2i_X509 failed");

- -			} else if ((evp = X509_get_pubkey(x509)) == NULL ||

- -			    EVP_PKEY_base_id(evp) != EVP_PKEY_RSA ||

- -			    EVP_PKEY_get0_RSA(evp) == NULL) {

- -				debug("X509_get_pubkey failed or no rsa");

- -			} else if ((rsa = RSAPublicKey_dup(

- -			    EVP_PKEY_get0_RSA(evp))) == NULL) {

- -				error("RSAPublicKey_dup");

- +			} else if ((evp = X509_get_pubkey(x509)) == NULL) {

- +				debug("X509_get_pubkey failed");

- +			} else {

- +				switch (EVP_PKEY_base_id(evp)) {

- +				case EVP_PKEY_RSA:

- +					if (EVP_PKEY_get0_RSA(evp) == NULL)

- +						debug("Missing RSA key");

- +					else if ((rsa = RSAPublicKey_dup(

- +					    EVP_PKEY_get0_RSA(evp))) == NULL)

- +						error("RSAPublicKey_dup failed");

- +					break;

- +				case EVP_PKEY_EC:

- +					if (EVP_PKEY_get0_EC_KEY(evp) == NULL)

- +						debug("Missing ECDSA key");

- +					else if ((ecdsa = EC_KEY_dup(

- +					    EVP_PKEY_get0_EC_KEY(evp))) == NULL)

- +						error("EC_KEY_dup failed");

- +					break;

- +				default:

- +					debug("not a RSA or ECDSA key");

- +					break;

- +				}

-  			}

-  			X509_free(x509);

-  			EVP_PKEY_free(evp);

- @@ -725,6 +1021,18 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  			key->rsa = rsa;

-  			key->type = KEY_RSA;

-  			key->flags |= SSHKEY_FLAG_EXT;

- +#ifdef ENABLE_PKCS11_ECDSA

- +		} else if (ecdsa &&

- +		    pkcs11_ecdsa_wrap(p, slotidx, &attribs[0], &attribs[1], ecdsa) == 0) {

- +			if ((key = sshkey_new(KEY_UNSPEC)) == NULL)

- +				fatal("sshkey_new failed");

- +			key->ecdsa = ecdsa;

- +			key->ecdsa_nid = sshkey_ecdsa_key_to_nid(key->ecdsa);

- +			key->type = KEY_ECDSA;

- +			key->flags |= SSHKEY_FLAG_EXT;

- +#endif /* ENABLE_PKCS11_ECDSA */

- +		}

- +		if (key) {

-  			if (pkcs11_key_included(keysp, nkeys, key)) {

-  				sshkey_free(key);

-  			} else {

- @@ -737,6 +1044,10 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  			}

-  		} else if (rsa) {

-  			RSA_free(rsa);

- +#ifdef ENABLE_PKCS11_ECDSA

- +		} else if (ecdsa) {

- +			EC_KEY_free(ecdsa);

- +#endif /* ENABLE_PKCS11_ECDSA */

-  		}

-  		for (i = 0; i < nattribs; i++)

-  			free(attribs[i].pValue);

- diff -up openssh/ssh-pkcs11-helper.c.pkcs11-ecdsa openssh/ssh-pkcs11-helper.c

- --- openssh/ssh-pkcs11-helper.c.pkcs11-ecdsa	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/ssh-pkcs11-helper.c	2018-10-12 14:05:55.023656999 +0200

- @@ -24,6 +24,17 @@

-  

-  #include "openbsd-compat/sys-queue.h"

-  

- +#include <openssl/rsa.h>

- +#ifdef OPENSSL_HAS_ECC

- +#include <openssl/ecdsa.h>

- +#if ((defined(LIBRESSL_VERSION_NUMBER) && \

- +	(LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \

- +	(defined(ECDSA_F_ECDSA_METHOD_NEW)) || \

- +	(OPENSSL_VERSION_NUMBER >= 0x00010100L)

- +#define ENABLE_PKCS11_ECDSA 1

- +#endif

- +#endif

- +

-  #include <stdarg.h>

-  #include <string.h>

-  #include <unistd.h>

- @@ -77,7 +88,7 @@ del_keys_by_name(char *name)

-  		if (!strcmp(ki->providername, name)) {

-  			TAILQ_REMOVE(&pkcs11_keylist, ki, next);

-  			free(ki->providername);

- -			sshkey_free(ki->key);

- +			pkcs11_del_key(ki->key);

-  			free(ki);

-  		}

-  	}

- @@ -172,6 +183,20 @@ process_del(void)

-  	sshbuf_free(msg);

-  }

-  

- +#ifdef ENABLE_PKCS11_ECDSA

- +static u_int EC_KEY_order_size(EC_KEY *key)

- +{

- +	const EC_GROUP *group = EC_KEY_get0_group(key);

- +	BIGNUM *order = BN_new();

- +	u_int nbytes = 0;

- +	if ((group != NULL) && (order != NULL) && EC_GROUP_get_order(group, order, NULL)) {

- +		nbytes = BN_num_bytes(order);

- +	}

- +	BN_clear_free(order);

- +	return nbytes;

- +}

- +#endif /* ENABLE_PKCS11_ECDSA */

- +

-  static void

-  process_sign(void)

-  {

- @@ -192,14 +217,38 @@ process_sign(void)

-  	else {

-  		if ((found = lookup_key(key)) != NULL) {

-  #ifdef WITH_OPENSSL

- -			int ret;

- -

- -			slen = RSA_size(key->rsa);

- -			signature = xmalloc(slen);

- -			if ((ret = RSA_private_encrypt(dlen, data, signature,

- -			    found->rsa, RSA_PKCS1_PADDING)) != -1) {

- -				slen = ret;

- -				ok = 0;

- +			if(found->type == KEY_RSA) {

- +				int ret;

- +				slen = RSA_size(key->rsa);

- +				signature = xmalloc(slen);

- +				if ((ret = RSA_private_encrypt(dlen, data, signature,

- +											   found->rsa, RSA_PKCS1_PADDING)) != -1) {

- +					slen = ret;

- +					ok = 0;

- +				}

- +#ifdef ENABLE_PKCS11_ECDSA

- +			} else if(found->type == KEY_ECDSA) {

- +				ECDSA_SIG *sig;

- +				const BIGNUM *r = NULL, *s = NULL;

- +				if ((sig = ECDSA_do_sign(data, dlen, found->ecdsa)) != NULL) {

- +					/* PKCS11 2.3.1 recommends both r and s to have the order size for

- +					   backward compatiblity */

- +					ECDSA_SIG_get0(sig, &r, &s);

- +					u_int o_len = EC_KEY_order_size(found->ecdsa);

- +					u_int r_len = BN_num_bytes(r);

- +					u_int s_len = BN_num_bytes(s);

- +					if (o_len > 0 && r_len <= o_len && s_len <= o_len) {

- +						signature = xcalloc(2, o_len);

- +						BN_bn2bin(r, signature + o_len - r_len);

- +						BN_bn2bin(s, signature + (2 * o_len) - s_len);

- +						slen = 2 * o_len;

- +						ok = 0;

- +					}

- +					ECDSA_SIG_free(sig);

- +				}

- +#endif /* ENABLE_PKCS11_ECDSA */

- +			} else {

- +				/* Unsupported type */

-  			}

-  #endif /* WITH_OPENSSL */

-  		}

- diff -up openssh/ssh-pkcs11.h.pkcs11-ecdsa openssh/ssh-pkcs11.h

- --- openssh/ssh-pkcs11.h.pkcs11-ecdsa	2018-10-12 14:05:55.021656982 +0200

- +++ openssh/ssh-pkcs11.h	2018-10-12 14:05:55.023656999 +0200

- @@ -20,6 +20,7 @@

-  int	pkcs11_init(int);

-  void	pkcs11_terminate(void);

-  int	pkcs11_add_provider(char *, char *, struct sshkey ***);

- +int	pkcs11_del_key(struct sshkey *);

-  int	pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***);

-  int	pkcs11_del_provider(char *);

-  int	pkcs11_uri_write(const struct sshkey *, FILE *);

@@ -1,4760 +0,0 @@ 

- diff -up openssh/authfd.c.pkcs11-uri openssh/authfd.c

- --- openssh/authfd.c.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/authfd.c	2018-10-12 13:52:55.450191401 +0200

- @@ -312,6 +312,8 @@ ssh_free_identitylist(struct ssh_identit

-  		if (idl->comments != NULL)

-  			free(idl->comments[i]);

-  	}

- +	free(idl->keys);

- +	free(idl->comments);

-  	free(idl);

-  }

-  

- diff -up openssh/configure.ac.pkcs11-uri openssh/configure.ac

- --- openssh/configure.ac.pkcs11-uri	2018-10-12 13:52:55.430191235 +0200

- +++ openssh/configure.ac	2018-10-12 13:52:55.451191409 +0200

- @@ -1987,12 +1987,14 @@ AC_LINK_IFELSE(

-  	[AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).])

-  ])

-  

- +SCARD_MSG="yes"

-  disable_pkcs11=

-  AC_ARG_ENABLE([pkcs11],

-  	[  --disable-pkcs11        disable PKCS#11 support code [no]],

-  	[

-  		if test "x$enableval" = "xno" ; then

-  			disable_pkcs11=1

- +			SCARD_MSG="no"

-  		fi

-  	]

-  )

- @@ -2008,6 +2010,40 @@ if test "x$openssl" = "xyes" && test "x$

-  	)

-  fi

-  

- +# Check whether we have a p11-kit, we got default provider on command line

- +DEFAULT_PKCS11_PROVIDER_MSG="no"

- +AC_ARG_WITH([default-pkcs11-provider],

- +	[  --with-default-pkcs11-provider[[=PATH]]   Use default pkcs11 provider (p11-kit detected by default)],

- +	[ if test "x$withval" != "xno" && test "x$disable_pkcs11" = "x"; then

- +		if test "x$withval" = "xyes" ; then

- +			AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])

- +			if test "x$PKGCONFIG" != "xno"; then

- +				AC_MSG_CHECKING([if $PKGCONFIG knows about p11-kit])

- +				if "$PKGCONFIG" "p11-kit-1"; then

- +					AC_MSG_RESULT([yes])

- +					use_pkgconfig_for_p11kit=yes

- +				else

- +					AC_MSG_RESULT([no])

- +				fi

- +			fi

- +		else

- +			PKCS11_PATH="${withval}"

- +		fi

- +		if test "x$use_pkgconfig_for_p11kit" = "xyes"; then

- +			PKCS11_PATH=`$PKGCONFIG --variable=proxy_module p11-kit-1`

- +		fi

- +		AC_CHECK_FILE("$PKCS11_PATH",

- +			[ AC_DEFINE_UNQUOTED([PKCS11_DEFAULT_PROVIDER], ["$PKCS11_PATH"], [Path to default PKCS#11 provider (p11-kit proxy)])

- +			  DEFAULT_PKCS11_PROVIDER_MSG="$PKCS11_PATH"

- +			],

- +			[ AC_MSG_ERROR([Requested PKCS11 provided not found]) ]

- +		)

- +	else

- +		AC_MSG_WARN([Needs PKCS11 support to enable default pkcs11 provider])

- +	fi ]

- +)

- +

- +

-  # IRIX has a const char return value for gai_strerror()

-  AC_CHECK_FUNCS([gai_strerror], [

-  	AC_DEFINE([HAVE_GAI_STRERROR])

- @@ -5458,6 +5494,7 @@ echo "                  BSD Auth support

-  echo "              Random number source: $RAND_MSG"

-  echo "             Privsep sandbox style: $SANDBOX_STYLE"

-  echo "                Vendor patch level: $SSH_VENDOR_PATCHLEVEL"

- +echo "          Default PKCS#11 provider: $DEFAULT_PKCS11_PROVIDER_MSG"

-  

-  echo ""

-  

- diff -up openssh/Makefile.in.pkcs11-uri openssh/Makefile.in

- --- openssh/Makefile.in.pkcs11-uri	2018-10-12 13:52:55.366190704 +0200

- +++ openssh/Makefile.in	2018-10-12 13:52:55.450191401 +0200

- @@ -102,7 +102,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \

-  	monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \

-  	kexgssc.o \

-  	msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \

- -	ssh-pkcs11.o smult_curve25519_ref.o \

- +	ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \

-  	poly1305.o chacha.o cipher-chachapoly.o \

-  	ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \

-  	sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \

- @@ -270,6 +270,8 @@ clean:	regressclean

-  	rm -f regress/unittests/match/test_match$(EXEEXT)

-  	rm -f regress/unittests/utf8/*.o

-  	rm -f regress/unittests/utf8/test_utf8$(EXEEXT)

- +	rm -f regress/unittests/pkcs11/*.o

- +	rm -f regress/unittests/pkcs11/test_pkcs11$(EXEEXT)

-  	rm -f regress/misc/kexfuzz/*.o

-  	rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)

-  	(cd openbsd-compat && $(MAKE) clean)

- @@ -300,6 +302,8 @@ distclean:	regressclean

-  	rm -f regress/unittests/match/test_match

-  	rm -f regress/unittests/utf8/*.o

-  	rm -f regress/unittests/utf8/test_utf8

- +	rm -f regress/unittests/pkcs11/*.o

- +	rm -f regress/unittests/pkcs11/test_pkcs11

-  	rm -f regress/misc/kexfuzz/*.o

-  	rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)

-  	(cd openbsd-compat && $(MAKE) distclean)

- @@ -484,6 +488,7 @@ regress-prep:

-  	$(MKDIR_P) `pwd`/regress/unittests/kex

-  	$(MKDIR_P) `pwd`/regress/unittests/match

-  	$(MKDIR_P) `pwd`/regress/unittests/utf8

- +	$(MKDIR_P) `pwd`/regress/unittests/pkcs11

-  	$(MKDIR_P) `pwd`/regress/misc/kexfuzz

-  	[ -f `pwd`/regress/Makefile ] || \

-  	    ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile

- @@ -502,6 +507,11 @@ regress/netcat$(EXEEXT): $(srcdir)/regre

-  	$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/netcat.c \

-  	$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)

-  

- +regress/soft-pkcs11.so: $(srcdir)/regress/soft-pkcs11.c $(REGRESSLIBS)

- +	$(CC) $(CFLAGS) $(CPPFLAGS) -fpic -c $(srcdir)/regress/soft-pkcs11.c \

- +	 -o $(srcdir)/regress/soft-pkcs11.o

- +	$(CC) -shared -o $@ $(srcdir)/regress/soft-pkcs11.o

- +

-  regress/check-perm$(EXEEXT): $(srcdir)/regress/check-perm.c $(REGRESSLIBS)

-  	$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/check-perm.c \

-  	$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)

- @@ -607,6 +617,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT

-  	    regress/unittests/test_helper/libtest_helper.a \

-  	    -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)

-  

- +UNITTESTS_TEST_PKCS11_OBJS=\

- +	regress/unittests/pkcs11/tests.o

- +

- +regress/unittests/pkcs11/test_pkcs11$(EXEEXT): \

- +    ${UNITTESTS_TEST_PKCS11_OBJS} \

- +    regress/unittests/test_helper/libtest_helper.a libssh.a

- +	$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_PKCS11_OBJS) \

- +	    regress/unittests/test_helper/libtest_helper.a \

- +	    -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)

- +

-  MISC_KEX_FUZZ_OBJS=\

-  	regress/misc/kexfuzz/kexfuzz.o

-  

- @@ -617,6 +637,7 @@ regress/misc/kexfuzz/kexfuzz$(EXEEXT): $

-  regress-binaries: regress/modpipe$(EXEEXT) \

-  	regress/setuid-allowed$(EXEEXT) \

-  	regress/netcat$(EXEEXT) \

- +	regress/soft-pkcs11.so \

-  	regress/check-perm$(EXEEXT) \

-  	regress/mkdtemp$(EXEEXT) \

-  	regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \

- @@ -627,6 +648,7 @@ regress-binaries: regress/modpipe$(EXEEX

-  	regress/unittests/kex/test_kex$(EXEEXT) \

-  	regress/unittests/match/test_match$(EXEEXT) \

-  	regress/unittests/utf8/test_utf8$(EXEEXT) \

- +	regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \

-  	regress/misc/kexfuzz/kexfuzz$(EXEEXT)

-  

-  tests interop-tests t-exec unit: regress-prep regress-binaries $(TARGETS)

- diff -up openssh/regress/agent-pkcs11.sh.pkcs11-uri openssh/regress/agent-pkcs11.sh

- --- openssh/regress/agent-pkcs11.sh.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/regress/agent-pkcs11.sh	2018-10-12 13:52:55.451191409 +0200

- @@ -4,10 +4,17 @@

-  tid="pkcs11 agent test"

-  

-  TEST_SSH_PIN=""

- -TEST_SSH_PKCS11=/usr/local/lib/soft-pkcs11.so.0.0

- +TEST_SSH_PKCS11=$OBJ/soft-pkcs11.so

-  

-  test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist"

-  

- +# requires ssh-agent built with correct path to ssh-pkcs11-helper

- +# otherwise it fails to start the helper

- +strings ${TEST_SSH_SSHAGENT} | grep "$TEST_SSH_SSHPKCS11HELPER"

- +if [ $? -ne 0 ]; then

- +	fatal "Needs to reconfigure with --libexecdir=\`pwd\` or so"

- +fi

- +

-  # setup environment for soft-pkcs11 token

-  SOFTPKCS11RC=$OBJ/pkcs11.info

-  export SOFTPKCS11RC

- @@ -23,7 +30,7 @@ notty() {

-  }

-  

-  trace "start agent"

- -eval `${SSHAGENT} -s` > /dev/null

- +eval `${SSHAGENT} -s -P "${OBJ}/*"` > /dev/null

-  r=$?

-  if [ $r -ne 0 ]; then

-  	fail "could not start ssh-agent: exit code $r"

- @@ -60,7 +67,7 @@ else

-  	fi

-  

-  	trace "remove pkcs11 keys"

- -	echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1

- +	${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1

-  	r=$?

-  	if [ $r -ne 0 ]; then

-  		fail "ssh-add -e failed: exit code $r"

- diff -up openssh/regress/locl.h.pkcs11-uri openssh/regress/locl.h

- --- openssh/regress/locl.h.pkcs11-uri	2018-10-12 13:52:55.451191409 +0200

- +++ openssh/regress/locl.h	2018-10-12 13:52:55.451191409 +0200

- @@ -0,0 +1,78 @@

- +/*

- + * Copyright (c) 2004, Stockholms universitet

- + * (Stockholm University, Stockholm Sweden)

- + * 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.

- + *

- + * 3. Neither the name of the university nor the names of its contributors

- + *    may be used to endorse or promote products derived from this software

- + *    without specific prior written permission.

- + *

- + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- + * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

- + * POSSIBILITY OF SUCH DAMAGE.

- + */

- +

- +/* $Id: locl.h,v 1.5 2005/08/28 15:30:31 lha Exp $ */

- +

- +#ifdef HAVE_CONFIG_H

- +#include <config.h>

- +#endif

- +

- +#include <openssl/err.h>

- +#include <openssl/evp.h>

- +#include <openssl/pem.h>

- +#include <openssl/rand.h>

- +#include <openssl/x509.h>

- +

- +#include <ctype.h>

- +#include <errno.h>

- +#include <pwd.h>

- +#include <stdarg.h>

- +#define _GNU_SOURCE

- +#include <stdio.h>

- +#include <stdlib.h>

- +#include <string.h>

- +#include <unistd.h>

- +

- +#include "../pkcs11.h"

- +

- +#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R)			\

- +{									\

- +  unsigned char *p;							\

- +  (BL) = i2d_##T((S), NULL);						\

- +  if ((BL) <= 0) {							\

- +     (R) = EINVAL;							\

- +  } else {								\

- +    (B) = malloc((BL));							\

- +    if ((B) == NULL) {							\

- +       (R) = ENOMEM;							\

- +    } else {								\

- +        p = (B);							\

- +        (R) = 0;							\

- +        (BL) = i2d_##T((S), &p);					\

- +        if ((BL) <= 0) {						\

- +           free((B));                                          		\

- +           (R) = EINVAL;						\

- +        }								\

- +    }									\

- +  }									\

- +}

- diff -up openssh/regress/Makefile.pkcs11-uri openssh/regress/Makefile

- --- openssh/regress/Makefile.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/regress/Makefile	2018-10-12 13:52:55.451191409 +0200

- @@ -109,9 +109,11 @@ CLEANFILES=	*.core actual agent-key.* au

-  		known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \

-  		modpipe netcat no_identity_config \

-  		pidfile putty.rsa2 ready regress.log \

- -		remote_pid revoked-* rsa rsa-agent rsa-agent.pub rsa.pub \

- +		remote_pid revoked-* rsa rsa-agent rsa-agent.pub \

- +		rsa-agent-cert.pub rsa.pub \

-  		rsa1 rsa1-agent rsa1-agent.pub rsa1.pub rsa_ssh2_cr.prv \

- -		rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \

- +		soft-pkcs11.so soft-pkcs11.o pkcs11*.crt pkcs11*.key \

- +		pkcs11.info rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \

-  		scp-ssh-wrapper.scp setuid-allowed sftp-server.log \

-  		sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \

-  		ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \

- @@ -226,6 +228,7 @@ unit:

-  		V="" ; \

-  		test "x${USE_VALGRIND}" = "x" || \

-  		    V=${.CURDIR}/valgrind-unit.sh ; \

- +		$$V ${.OBJDIR}/unittests/pkcs11/test_pkcs11 ; \

-  		$$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \

-  		$$V ${.OBJDIR}/unittests/sshkey/test_sshkey \

-  			-d ${.CURDIR}/unittests/sshkey/testdata ; \

- diff -up openssh/regress/pkcs11.sh.pkcs11-uri openssh/regress/pkcs11.sh

- --- openssh/regress/pkcs11.sh.pkcs11-uri	2018-10-12 13:52:55.451191409 +0200

- +++ openssh/regress/pkcs11.sh	2018-10-12 13:52:55.451191409 +0200

- @@ -0,0 +1,300 @@

- +#

- +#  Copyright (c) 2017 Red Hat

- +#

- +#  Authors: Jakub Jelen <jjelen@redhat.com>

- +#

- +#  Permission to use, copy, modify, and distribute this software for any

- +#  purpose with or without fee is hereby granted, provided that the above

- +#  copyright notice and this permission notice appear in all copies.

- +#

- +#  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES

- +#  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF

- +#  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR

- +#  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES

- +#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN

- +#  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF

- +#  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

- +

- +tid="pkcs11 tests with soft token"

- +

- +TEST_SSH_PIN=""

- +TEST_SSH_PKCS11=$OBJ/soft-pkcs11.so

- +

- +test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist"

- +

- +# requires ssh-agent built with correct path to ssh-pkcs11-helper

- +# otherwise it fails to start the helper

- +strings ${TEST_SSH_SSHAGENT} | grep "$TEST_SSH_SSHPKCS11HELPER"

- +if [ $? -ne 0 ]; then

- +	fatal "Needs to reconfigure with --libexecdir=\`pwd\` or so"

- +fi

- +

- +# setup environment for soft-pkcs11 token

- +SOFTPKCS11RC=$OBJ/pkcs11.info

- +rm -f $SOFTPKCS11RC

- +export SOFTPKCS11RC

- +# prevent ssh-agent from calling ssh-askpass

- +SSH_ASKPASS=/usr/bin/true

- +export SSH_ASKPASS

- +unset DISPLAY

- +

- +# start command w/o tty, so ssh accepts pin from stdin (from agent-pkcs11.sh)

- +notty() {

- +	perl -e 'use POSIX; POSIX::setsid();

- +	    if (fork) { wait; exit($? >> 8); } else { exec(@ARGV) }' "$@"

- +}

- +

- +create_key() {

- +	ID=$1

- +	LABEL=$2

- +	rm -f $OBJ/pkcs11-${ID}.key $OBJ/pkcs11-${ID}.crt

- +	openssl genrsa -out $OBJ/pkcs11-${ID}.key 2048 > /dev/null 2>&1

- +	chmod 600 $OBJ/pkcs11-${ID}.key

- +	openssl req -key $OBJ/pkcs11-${ID}.key -new -x509 \

- +	    -out $OBJ/pkcs11-${ID}.crt -text -subj '/CN=pkcs11 test' >/dev/null

- +	printf "${ID}\t${LABEL}\t$OBJ/pkcs11-${ID}.crt\t$OBJ/pkcs11-${ID}.key\n" \

- +	    >> $SOFTPKCS11RC

- +}

- +

- +trace "Create a key pairs on soft token"

- +ID1="02"

- +ID2="04"

- +create_key "$ID1" "SSH RSA Key"

- +create_key "$ID2" "SSH RSA Key 2"

- +

- +trace "List the keys in the ssh-keygen with PKCS#11 URIs"

- +${SSHKEYGEN} -D ${TEST_SSH_PKCS11} > $OBJ/token_keys

- +if [ $? -ne 0 ]; then

- +	fail "keygen fails to enumerate keys on PKCS#11 token"

- +fi

- +grep "pkcs11:" $OBJ/token_keys > /dev/null

- +if [ $? -ne 0 ]; then

- +	fail "The keys from ssh-keygen do not contain PKCS#11 URI as a comment"

- +fi

- +tail -n 1 $OBJ/token_keys > $OBJ/authorized_keys_$USER

- +

- +

- +trace "Simple connect with ssh (without PKCS#11 URI)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -I ${TEST_SSH_PKCS11} \

- +    -F $OBJ/ssh_proxy somehost exit 5

- +r=$?

- +if [ $r -ne 5 ]; then

- +	fail "ssh connect with pkcs11 failed (exit code $r)"

- +fi

- +

- +

- +trace "Connect with PKCS#11 URI"

- +trace "  (second key should succeed)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \

- +    -i "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" somehost exit 5

- +r=$?

- +if [ $r -ne 5 ]; then

- +	fail "ssh connect with PKCS#11 URI failed (exit code $r)"

- +fi

- +

- +trace "  (first key should fail)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \

- +     -i "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" somehost exit 5

- +r=$?

- +if [ $r -eq 5 ]; then

- +	fail "ssh connect with PKCS#11 URI succeeded (should fail)"

- +fi

- +

- +trace "Connect with various filtering options in PKCS#11 URI"

- +trace "  (by object label, second key should succeed)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \

- +    -i "pkcs11:object=SSH%20RSA%20Key%202?module-path=${TEST_SSH_PKCS11}" somehost exit 5

- +r=$?

- +if [ $r -ne 5 ]; then

- +	fail "ssh connect with PKCS#11 URI failed (exit code $r)"

- +fi

- +

- +trace "  (by object label, first key should fail)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \

- +     -i "pkcs11:object=SSH%20RSA%20Key?module-path=${TEST_SSH_PKCS11}" somehost exit 5

- +r=$?

- +if [ $r -eq 5 ]; then

- +	fail "ssh connect with PKCS#11 URI succeeded (should fail)"

- +fi

- +

- +trace "  (by token label, second key should succeed)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \

- +    -i "pkcs11:id=${ID2};token=SoftToken%20(token)?module-path=${TEST_SSH_PKCS11}" somehost exit 5

- +r=$?

- +if [ $r -ne 5 ]; then

- +	fail "ssh connect with PKCS#11 URI failed (exit code $r)"

- +fi

- +

- +trace "  (by wrong token label, should fail)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \

- +     -i "pkcs11:token=SoftToken?module-path=${TEST_SSH_PKCS11}" somehost exit 5

- +r=$?

- +if [ $r -eq 5 ]; then

- +	fail "ssh connect with PKCS#11 URI succeeded (should fail)"

- +fi

- +

- +

- +

- +

- +trace "Test PKCS#11 URI specification in configuration files"

- +echo "IdentityFile \"pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}\"" \

- +    >> $OBJ/ssh_proxy

- +trace "  (second key should succeed)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5

- +r=$?

- +if [ $r -ne 5 ]; then

- +	fail "ssh connect with PKCS#11 URI in config failed (exit code $r)"

- +fi

- +

- +trace "  (first key should fail)"

- +head -n 1 $OBJ/token_keys > $OBJ/authorized_keys_$USER

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5

- +r=$?

- +if [ $r -eq 5 ]; then

- +	fail "ssh connect with PKCS#11 URI in config succeeded (should fail)"

- +fi

- +sed -i -e "/IdentityFile/d" $OBJ/ssh_proxy

- +

- +trace "Test PKCS#11 URI specification in configuration files with bogus spaces"

- +echo "IdentityFile \"    pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}    \"" \

- +    >> $OBJ/ssh_proxy

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5

- +r=$?

- +if [ $r -ne 5 ]; then

- +	fail "ssh connect with PKCS#11 URI with bogus spaces in config failed" \

- +	    "(exit code $r)"

- +fi

- +sed -i -e "/IdentityFile/d" $OBJ/ssh_proxy

- +

- +

- +trace "Combination of PKCS11Provider and PKCS11URI on commandline"

- +trace "  (first key should succeed)"

- +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \

- +    -i "pkcs11:id=${ID1}" -I ${TEST_SSH_PKCS11} somehost exit 5

- +r=$?

- +if [ $r -ne 5 ]; then

- +	fail "ssh connect with PKCS#11 URI and provider combination" \

- +	    "failed (exit code $r)"

- +fi

- +

- +trace "Regress: Missing provider in PKCS11URI option"

- +${SSH} -F $OBJ/ssh_proxy \

- +    -o IdentityFile=\"pkcs11:token=segfault\" somehost exit 5

- +r=$?

- +if [ $r -eq 139 ]; then

- +	fail "ssh connect with missing provider_id from configuration option" \

- +	    "crashed (exit code $r)"

- +fi

- +

- +

- +trace "SSH Agent can work with PKCS#11 URI"

- +trace "start the agent"

- +eval `${SSHAGENT} -s -P "${OBJ}/*"` > /dev/null

- +

- +r=$?

- +if [ $r -ne 0 ]; then

- +	fail "could not start ssh-agent: exit code $r"

- +else

- +	trace "add whole provider to agent"

- +	echo ${TEST_SSH_PIN} | notty ${SSHADD} \

- +	    "pkcs11:?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1

- +	r=$?

- +	if [ $r -ne 0 ]; then

- +		fail "ssh-add failed with whole provider: exit code $r"

- +	fi

- +

- +	trace " pkcs11 list via agent (all keys)"

- +	${SSHADD} -l > /dev/null 2>&1

- +	r=$?

- +	if [ $r -ne 0 ]; then

- +		fail "ssh-add -l failed with whole provider: exit code $r"

- +	fi

- +

- +	trace " pkcs11 connect via agent (all keys)"

- +	${SSH} -F $OBJ/ssh_proxy somehost exit 5

- +	r=$?

- +	if [ $r -ne 5 ]; then

- +		fail "ssh connect failed with whole provider (exit code $r)"

- +	fi

- +

- +	trace " remove pkcs11 keys (all keys)"

- +	${SSHADD} -d "pkcs11:?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1

- +	r=$?

- +	if [ $r -ne 0 ]; then

- +		fail "ssh-add -d failed with whole provider: exit code $r"

- +	fi

- +

- +	trace "add only first key to the agent"

- +	echo ${TEST_SSH_PIN} | notty ${SSHADD} \

- +	    "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1

- +	r=$?

- +	if [ $r -ne 0 ]; then

- +		fail "ssh-add failed with first key: exit code $r"

- +	fi

- +

- +	trace " pkcs11 connect via agent (first key)"

- +	${SSH} -F $OBJ/ssh_proxy somehost exit 5

- +	r=$?

- +	if [ $r -ne 5 ]; then

- +		fail "ssh connect failed with first key (exit code $r)"

- +	fi

- +

- +	trace " remove first pkcs11 key"

- +	${SSHADD} -d "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" \

- +	    > /dev/null 2>&1

- +	r=$?

- +	if [ $r -ne 0 ]; then

- +		fail "ssh-add -d failed with first key: exit code $r"

- +	fi

- +

- +	trace "add only second key to the agent"

- +	echo ${TEST_SSH_PIN} | notty ${SSHADD} \

- +	    "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1

- +	r=$?

- +	if [ $r -ne 0 ]; then

- +		fail "ssh-add failed with second key: exit code $r"

- +	fi

- +

- +	trace " pkcs11 connect via agent (second key should fail)"

- +	${SSH} -F $OBJ/ssh_proxy somehost exit 5

- +	r=$?

- +	if [ $r -eq 5 ]; then

- +		fail "ssh connect passed without key (should fail)"

- +	fi

- +

- +	trace "add also the first key to the agent"

- +	echo ${TEST_SSH_PIN} | notty ${SSHADD} \

- +	    "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1

- +	r=$?

- +	if [ $r -ne 0 ]; then

- +		fail "ssh-add failed with first key: exit code $r"

- +	fi

- +

- +	trace " remove second pkcs11 key"

- +	${SSHADD} -d "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" \

- +	    > /dev/null 2>&1

- +	r=$?

- +	if [ $r -ne 0 ]; then

- +		fail "ssh-add -d failed with second key: exit code $r"

- +	fi

- +

- +	trace " remove already-removed pkcs11 key should fail"

- +	${SSHADD} -d "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" \

- +	    > /dev/null 2>&1

- +	r=$?

- +	if [ $r -eq 0 ]; then

- +		fail "ssh-add -d passed with non-existing key (should fail)"

- +	fi

- +

- +	trace " pkcs11 connect via agent (the first key should be still usable)"

- +	${SSH} -F $OBJ/ssh_proxy somehost exit 5

- +	r=$?

- +	if [ $r -ne 5 ]; then

- +		fail "ssh connect failed with first key (after removing second): exit code $r"

- +	fi

- +

- +	trace "kill agent"

- +	${SSHAGENT} -k > /dev/null

- +fi

- +

- +rm -rf $OBJ/.tokens $OBJ/token_keys

- diff -up openssh/regress/soft-pkcs11.c.pkcs11-uri openssh/regress/soft-pkcs11.c

- --- openssh/regress/soft-pkcs11.c.pkcs11-uri	2018-10-12 13:52:55.452191417 +0200

- +++ openssh/regress/soft-pkcs11.c	2018-10-12 13:52:55.452191417 +0200

- @@ -0,0 +1,2058 @@

- +/*

- + * Copyright (c) 2004-2006, Stockholms universitet

- + * (Stockholm University, Stockholm Sweden)

- + * 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.

- + *

- + * 3. Neither the name of the university nor the names of its contributors

- + *    may be used to endorse or promote products derived from this software

- + *    without specific prior written permission.

- + *

- + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

- + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

- + * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE

- + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

- + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

- + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

- + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

- + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

- + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

- + * POSSIBILITY OF SUCH DAMAGE.

- + */

- +

- +#include "locl.h"

- +

- +/* RCSID("$Id: main.c,v 1.24 2006/01/11 12:42:53 lha Exp $"); */

- +

- +#define OBJECT_ID_MASK		0xfff

- +#define HANDLE_OBJECT_ID(h)	((h) & OBJECT_ID_MASK)

- +#define OBJECT_ID(obj)		HANDLE_OBJECT_ID((obj)->object_handle)

- +

- +#if OPENSSL_VERSION_NUMBER < 0x10100000L

- + #define RSA_PKCS1_SSLeay RSA_PKCS1_OpenSSL

- +#endif

- +

- +struct st_attr {

- +    CK_ATTRIBUTE attribute;

- +    int secret;

- +};

- +

- +struct st_object {

- +    CK_OBJECT_HANDLE object_handle;

- +    struct st_attr *attrs;

- +    int num_attributes;

- +    enum {

- +	STO_T_CERTIFICATE,

- +	STO_T_PRIVATE_KEY,

- +	STO_T_PUBLIC_KEY

- +    } type;

- +    union {

- +	X509 *cert;

- +	EVP_PKEY *public_key;

- +	struct {

- +	    const char *file;

- +	    EVP_PKEY *key;

- +	    X509 *cert;

- +	} private_key;

- +    } u;

- +};

- +

- +static struct soft_token {

- +    CK_VOID_PTR application;

- +    CK_NOTIFY notify;

- +    struct {

- +	struct st_object **objs;

- +	int num_objs;

- +    } object;

- +    struct {

- +	int hardware_slot;

- +	int app_error_fatal;

- +	int login_done;

- +    } flags;

- +    int open_sessions;

- +    struct session_state {

- +	CK_SESSION_HANDLE session_handle;

- +

- +	struct {

- +	    CK_ATTRIBUTE *attributes;

- +	    CK_ULONG num_attributes;

- +	    int next_object;

- +	} find;

- +

- +	int encrypt_object;

- +	CK_MECHANISM_PTR encrypt_mechanism;

- +	int decrypt_object;

- +	CK_MECHANISM_PTR decrypt_mechanism;

- +	int sign_object;

- +	CK_MECHANISM_PTR sign_mechanism;

- +	int verify_object;

- +	CK_MECHANISM_PTR verify_mechanism;

- +	int digest_object;

- +    } state[10];

- +#define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))

- +    FILE *logfile;

- +} soft_token;

- +

- +static void

- +application_error(const char *fmt, ...)

- +{

- +    va_list ap;

- +    va_start(ap, fmt);

- +    vprintf(fmt, ap);

- +    va_end(ap);

- +    if (soft_token.flags.app_error_fatal)

- +	abort();

- +}

- +

- +static void

- +st_logf(const char *fmt, ...)

- +{

- +    va_list ap;

- +    if (soft_token.logfile == NULL)

- +	return;

- +    va_start(ap, fmt);

- +    vfprintf(soft_token.logfile, fmt, ap);

- +    va_end(ap);

- +    fflush(soft_token.logfile);

- +}

- +

- +static void

- +snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)

- +{

- +    int len;

- +    va_list ap;

- +    len = vsnprintf(str, size, fmt, ap);

- +    va_end(ap);

- +    if (len < 0 || len > (int) size)

- +	return;

- +    while(len < (int) size)

- +	str[len++] = fillchar;

- +}

- +

- +#ifndef TEST_APP

- +#define printf error_use_st_logf

- +#endif

- +

- +#define VERIFY_SESSION_HANDLE(s, state)			\

- +{							\

- +    CK_RV ret;						\

- +    ret = verify_session_handle(s, state);		\

- +    if (ret != CKR_OK) {				\

- +	/* return CKR_OK */;				\

- +    }							\

- +}

- +

- +static CK_RV

- +verify_session_handle(CK_SESSION_HANDLE hSession,

- +		      struct session_state **state)

- +{

- +    size_t i;

- +

- +    for (i = 0; i < MAX_NUM_SESSION; i++){

- +	if (soft_token.state[i].session_handle == hSession)

- +	    break;

- +    }

- +    if (i == MAX_NUM_SESSION) {

- +	application_error("use of invalid handle: 0x%08lx\n",

- +			  (unsigned long)hSession);

- +	return CKR_SESSION_HANDLE_INVALID;

- +    }

- +    if (state)

- +	*state = &soft_token.state[i];

- +    return CKR_OK;

- +}

- +

- +static CK_RV

- +object_handle_to_object(CK_OBJECT_HANDLE handle,

- +			struct st_object **object)

- +{

- +    int i = HANDLE_OBJECT_ID(handle);

- +

- +    *object = NULL;

- +    if (i >= soft_token.object.num_objs)

- +	return CKR_ARGUMENTS_BAD;

- +    if (soft_token.object.objs[i] == NULL)

- +	return CKR_ARGUMENTS_BAD;

- +    if (soft_token.object.objs[i]->object_handle != handle)

- +	return CKR_ARGUMENTS_BAD;

- +    *object = soft_token.object.objs[i];

- +    return CKR_OK;

- +}

- +

- +static int

- +attributes_match(const struct st_object *obj,

- +		 const CK_ATTRIBUTE *attributes,

- +		 CK_ULONG num_attributes)

- +{

- +    CK_ULONG i;

- +    int j;

- +    st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));

- +

- +    for (i = 0; i < num_attributes; i++) {

- +	int match = 0;

- +	for (j = 0; j < obj->num_attributes; j++) {

- +	    if (attributes[i].type == obj->attrs[j].attribute.type &&

- +		attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen &&

- +		memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue,

- +		       attributes[i].ulValueLen) == 0) {

- +		match = 1;

- +		break;

- +	    }

- +	}

- +	if (match == 0) {

- +	    st_logf("type %d attribute have no match\n", attributes[i].type);

- +	    return 0;

- +	}

- +    }

- +    st_logf("attribute matches\n");

- +    return 1;

- +}

- +

- +static void

- +print_attributes(const CK_ATTRIBUTE *attributes,

- +		 CK_ULONG num_attributes)

- +{

- +    CK_ULONG i;

- +

- +    st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);

- +

- +    for (i = 0; i < num_attributes; i++) {

- +	st_logf("  type: ");

- +	switch (attributes[i].type) {

- +	case CKA_TOKEN: {

- +	    CK_BBOOL *ck_true;

- +	    if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {

- +		application_error("token attribute wrong length\n");

- +		break;

- +	    }

- +	    ck_true = attributes[i].pValue;

- +	    st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");

- +	    break;

- +	}

- +	case CKA_CLASS: {

- +	    CK_OBJECT_CLASS *class;

- +	    if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {

- +		application_error("class attribute wrong length\n");

- +		break;

- +	    }

- +	    class = attributes[i].pValue;

- +	    st_logf("class ");

- +	    switch (*class) {

- +	    case CKO_CERTIFICATE:

- +		st_logf("certificate");

- +		break;

- +	    case CKO_PUBLIC_KEY:

- +		st_logf("public key");

- +		break;

- +	    case CKO_PRIVATE_KEY:

- +		st_logf("private key");

- +		break;

- +	    case CKO_SECRET_KEY:

- +		st_logf("secret key");

- +		break;

- +	    case CKO_DOMAIN_PARAMETERS:

- +		st_logf("domain parameters");

- +		break;

- +	    default:

- +		st_logf("[class %lx]", (long unsigned)*class);

- +		break;

- +	    }

- +	    break;

- +	}

- +	case CKA_PRIVATE:

- +	    st_logf("private");

- +	    break;

- +	case CKA_LABEL:

- +	    st_logf("label");

- +	    break;

- +	case CKA_APPLICATION:

- +	    st_logf("application");

- +	    break;

- +	case CKA_VALUE:

- +	    st_logf("value");

- +	    break;

- +	case CKA_ID:

- +	    st_logf("id");

- +	    break;

- +	default:

- +	    st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);

- +	    break;

- +	}

- +	st_logf("\n");

- +    }

- +}

- +

- +static struct st_object *

- +add_st_object(void)

- +{

- +    struct st_object *o, **objs;

- +    int i;

- +

- +    o = malloc(sizeof(*o));

- +    if (o == NULL)

- +	return NULL;

- +    memset(o, 0, sizeof(*o));

- +    o->attrs = NULL;

- +    o->num_attributes = 0;

- +

- +    for (i = 0; i < soft_token.object.num_objs; i++) {

- +	if (soft_token.object.objs == NULL) {

- +	    soft_token.object.objs[i] = o;

- +	    break;

- +	}

- +    }

- +    if (i == soft_token.object.num_objs) {

- +	objs = realloc(soft_token.object.objs,

- +		       (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0]));

- +	if (objs == NULL) {

- +	    free(o);

- +	    return NULL;

- +	}

- +	soft_token.object.objs = objs;

- +	soft_token.object.objs[soft_token.object.num_objs++] = o;

- +    }	

- +    soft_token.object.objs[i]->object_handle =

- +	(random() & (~OBJECT_ID_MASK)) | i;

- +

- +    return o;

- +}

- +

- +static CK_RV

- +add_object_attribute(struct st_object *o,

- +		     int secret,

- +		     CK_ATTRIBUTE_TYPE type,

- +		     CK_VOID_PTR pValue,

- +		     CK_ULONG ulValueLen)

- +{

- +    struct st_attr *a;

- +    int i;

- +

- +    i = o->num_attributes;

- +    a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));

- +    if (a == NULL)

- +	return CKR_DEVICE_MEMORY;

- +    o->attrs = a;

- +    o->attrs[i].secret = secret;

- +    o->attrs[i].attribute.type = type;

- +    o->attrs[i].attribute.pValue = malloc(ulValueLen);

- +    if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)

- +	return CKR_DEVICE_MEMORY;

- +    memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);

- +    o->attrs[i].attribute.ulValueLen = ulValueLen;

- +    o->num_attributes++;

- +

- +    return CKR_OK;

- +}

- +

- +static CK_RV

- +add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)

- +{

- +    switch (key_type) {

- +    case CKK_RSA: {

- +	CK_BYTE *modulus = NULL;

- +	size_t modulus_len = 0;

- +	CK_ULONG modulus_bits = 0;

- +	CK_BYTE *exponent = NULL;

- +	size_t exponent_len = 0;

- +	RSA* rsa = NULL;

- +	const BIGNUM *n = NULL, *e = NULL;

- +

- +	rsa = EVP_PKEY_get0_RSA(key);

- +	RSA_get0_key(rsa, &n, &e, NULL);

- +

- +	modulus_bits = BN_num_bits(n);

- +

- +	modulus_len = BN_num_bytes(n);

- +	modulus = malloc(modulus_len);

- +	BN_bn2bin(n, modulus);

- +	

- +	exponent_len = BN_num_bytes(e);

- +	exponent = malloc(exponent_len);

- +	BN_bn2bin(e, exponent);

- +	

- +	add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);

- +	add_object_attribute(o, 0, CKA_MODULUS_BITS,

- +			     &modulus_bits, sizeof(modulus_bits));

- +	add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,

- +			     exponent, exponent_len);

- +

- +	RSA_set_method(rsa, RSA_PKCS1_OpenSSL());

- +

- +	free(modulus);

- +	free(exponent);

- +    }

- +    default:

- +	/* XXX */

- +	break;

- +    }

- +    return CKR_OK;

- +}

- +

- +

- +static int

- +pem_callback(char *buf, int num, int w, void *key)

- +{

- +    return -1;

- +}

- +

- +

- +static CK_RV

- +add_certificate(char *label,

- +		const char *cert_file,

- +		const char *private_key_file,

- +		char *id,

- +		int anchor)

- +{

- +    struct st_object *o = NULL;

- +    CK_BBOOL bool_true = CK_TRUE;

- +    CK_BBOOL bool_false = CK_FALSE;

- +    CK_OBJECT_CLASS c;

- +    CK_CERTIFICATE_TYPE cert_type = CKC_X_509;

- +    CK_KEY_TYPE key_type;

- +    CK_MECHANISM_TYPE mech_type;

- +    void *cert_data = NULL;

- +    size_t cert_length;

- +    void *subject_data = NULL;

- +    size_t subject_length;

- +    void *issuer_data = NULL;

- +    size_t issuer_length;

- +    void *serial_data = NULL;

- +    size_t serial_length;

- +    CK_RV ret = CKR_GENERAL_ERROR;

- +    X509 *cert;

- +    EVP_PKEY *public_key;

- +

- +    size_t id_len = strlen(id);

- +

- +    {

- +	FILE *f;

- +	

- +	f = fopen(cert_file, "r");

- +	if (f == NULL) {

- +	    st_logf("failed to open file %s\n", cert_file);

- +	    return CKR_GENERAL_ERROR;

- +	}

- +

- +	cert = PEM_read_X509(f, NULL, NULL, NULL);

- +	fclose(f);

- +	if (cert == NULL) {

- +	    st_logf("failed reading PEM cert\n");

- +	    return CKR_GENERAL_ERROR;

- +	}

- +

- +	OPENSSL_ASN1_MALLOC_ENCODE(X509, cert_data, cert_length, cert, ret);

- +	if (ret)

- +	    goto out;

- +

- +	OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, issuer_data, issuer_length,

- +				   X509_get_issuer_name(cert), ret);

- +	if (ret)

- +	    goto out;

- +

- +	OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length,

- +				   X509_get_subject_name(cert), ret);

- +	if (ret)

- +	    goto out;

- +

- +	OPENSSL_ASN1_MALLOC_ENCODE(ASN1_INTEGER, serial_data, serial_length,

- +				   X509_get_serialNumber(cert), ret);

- +	if (ret)

- +	    goto out;

- +

- +    }

- +

- +    st_logf("done parsing, adding to internal structure\n");

- +

- +    o = add_st_object();

- +    if (o == NULL) {

- +	ret = CKR_DEVICE_MEMORY;

- +	goto out;

- +    }

- +    o->type = STO_T_CERTIFICATE;

- +    o->u.cert = cert;

- +    public_key = X509_get_pubkey(o->u.cert);

- +

- +    switch (EVP_PKEY_base_id(public_key)) {

- +    case EVP_PKEY_RSA:

- +	key_type = CKK_RSA;

- +	break;

- +    case EVP_PKEY_DSA:

- +	key_type = CKK_DSA;

- +	break;

- +    default:

- +	/* XXX */

- +	break;

- +    }

- +

- +    c = CKO_CERTIFICATE;

- +    add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));

- +    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));

- +    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));

- +    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));

- +    add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));

- +

- +    add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));

- +    add_object_attribute(o, 0, CKA_ID, id, id_len);

- +

- +    add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);

- +    add_object_attribute(o, 0, CKA_ISSUER, issuer_data, issuer_length);

- +    add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data, serial_length);

- +    add_object_attribute(o, 0, CKA_VALUE, cert_data, cert_length);

- +    if (anchor)

- +	add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));

- +    else

- +	add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));

- +

- +    st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));

- +

- +    o = add_st_object();

- +    if (o == NULL) {

- +	ret = CKR_DEVICE_MEMORY;

- +	goto out;

- +    }

- +    o->type = STO_T_PUBLIC_KEY;

- +    o->u.public_key = public_key;

- +

- +    c = CKO_PUBLIC_KEY;

- +    add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));

- +    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));

- +    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));

- +    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));

- +    add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));

- +

- +    add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));

- +    add_object_attribute(o, 0, CKA_ID, id, id_len);

- +    add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */

- +    add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */

- +    add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));

- +    add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));

- +    mech_type = CKM_RSA_X_509;

- +    add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));

- +

- +    add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);

- +    add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));

- +    add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));

- +    add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));

- +    add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));

- +    add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));

- +

- +    add_pubkey_info(o, key_type, public_key);

- +

- +    st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));

- +

- +    if (private_key_file) {

- +	CK_FLAGS flags;

- +	FILE *f;

- +

- +	o = add_st_object();

- +	if (o == NULL) {

- +	    ret = CKR_DEVICE_MEMORY;

- +	    goto out;

- +	}

- +	o->type = STO_T_PRIVATE_KEY;

- +	o->u.private_key.file = strdup(private_key_file);

- +	o->u.private_key.key = NULL;

- +

- +	o->u.private_key.cert = cert;

- +

- +	c = CKO_PRIVATE_KEY;

- +	add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));

- +	add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));

- +	add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));

- +	add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));

- +	add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));

- +

- +	add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));

- +	add_object_attribute(o, 0, CKA_ID, id, id_len);

- +	add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */

- +	add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */

- +	add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));

- +	add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));

- +	mech_type = CKM_RSA_X_509;

- +	add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));

- +

- +	add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);

- +	add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));

- +	add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));

- +	flags = 0;

- +	add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));

- +

- +	add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));

- +	add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));

- +	add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));

- +	add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));

- +	add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));

- +	add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));

- +

- +	add_pubkey_info(o, key_type, public_key);

- +

- +	f = fopen(private_key_file, "r");

- +	if (f == NULL) {

- +	    st_logf("failed to open private key\n");

- +	    return CKR_GENERAL_ERROR;

- +	}

- +

- +	o->u.private_key.key = PEM_read_PrivateKey(f, NULL, pem_callback, NULL);

- +	fclose(f);

- +	if (o->u.private_key.key == NULL) {

- +	    st_logf("failed to read private key a startup\n");

- +	    /* don't bother with this failure for now,

- +	       fix it at C_Login time */;

- +	} else {

- +	    /* XXX verify keytype */

- +

- +	    if (key_type == CKK_RSA) {

- +		RSA *rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);

- +		RSA_set_method(rsa, RSA_PKCS1_OpenSSL());

- +	    }

- +

- +	    if (X509_check_private_key(cert, o->u.private_key.key) != 1) {

- +		EVP_PKEY_free(o->u.private_key.key);

- +		o->u.private_key.key = NULL;

- +		st_logf("private key doesn't verify\n");

- +	    } else {

- +		st_logf("private key usable\n");

- +		soft_token.flags.login_done = 1;

- +	    }

- +	}

- +    }

- +

- +    ret = CKR_OK;

- + out:

- +    if (ret != CKR_OK) {

- +	st_logf("something went wrong when adding cert!\n");

- +

- +	/* XXX wack o */;

- +    }

- +    free(cert_data);

- +    free(serial_data);

- +    free(issuer_data);

- +    free(subject_data);

- +

- +    return ret;

- +}

- +

- +static void

- +find_object_final(struct session_state *state)

- +{

- +    if (state->find.attributes) {

- +	CK_ULONG i;

- +

- +	for (i = 0; i < state->find.num_attributes; i++) {

- +	    if (state->find.attributes[i].pValue)

- +		free(state->find.attributes[i].pValue);

- +	}

- +	free(state->find.attributes);

- +	state->find.attributes = NULL;

- +	state->find.num_attributes = 0;

- +	state->find.next_object = -1;

- +    }

- +}

- +

- +static void

- +reset_crypto_state(struct session_state *state)

- +{

- +    state->encrypt_object = -1;

- +    if (state->encrypt_mechanism)

- +	free(state->encrypt_mechanism);

- +    state->encrypt_mechanism = NULL_PTR;

- +    state->decrypt_object = -1;

- +    if (state->decrypt_mechanism)

- +	free(state->decrypt_mechanism);

- +    state->decrypt_mechanism = NULL_PTR;

- +    state->sign_object = -1;

- +    if (state->sign_mechanism)

- +	free(state->sign_mechanism);

- +    state->sign_mechanism = NULL_PTR;

- +    state->verify_object = -1;

- +    if (state->verify_mechanism)

- +	free(state->verify_mechanism);

- +    state->verify_mechanism = NULL_PTR;

- +    state->digest_object = -1;

- +}

- +

- +static void

- +close_session(struct session_state *state)

- +{

- +    if (state->find.attributes) {

- +	application_error("application didn't do C_FindObjectsFinal\n");

- +	find_object_final(state);

- +    }

- +

- +    state->session_handle = CK_INVALID_HANDLE;

- +    soft_token.application = NULL_PTR;

- +    soft_token.notify = NULL_PTR;

- +    reset_crypto_state(state);

- +}

- +

- +static const char *

- +has_session(void)

- +{

- +    return soft_token.open_sessions > 0 ? "yes" : "no";

- +}

- +

- +static void

- +read_conf_file(const char *fn)

- +{

- +    char buf[1024], *cert, *key, *id, *label, *s, *p;

- +    int anchor;

- +    FILE *f;

- +

- +    f = fopen(fn, "r");

- +    if (f == NULL) {

- +	st_logf("can't open configuration file %s\n", fn);

- +	return;

- +    }

- +

- +    while(fgets(buf, sizeof(buf), f) != NULL) {

- +	buf[strcspn(buf, "\n")] = '\0';

- +

- +	anchor = 0;

- +

- +	st_logf("line: %s\n", buf);

- +

- +	p = buf;

- +	while (isspace(*p))

- +	    p++;

- +	if (*p == '#')

- +	    continue;

- +	while (isspace(*p))

- +	    p++;

- +

- +	s = NULL;

- +	id = strtok_r(p, "\t", &s);

- +	if (id == NULL)

- +	    continue;

- +	label = strtok_r(NULL, "\t", &s);

- +	if (label == NULL)

- +	    continue;

- +	cert = strtok_r(NULL, "\t", &s);

- +	if (cert == NULL)

- +	    continue;

- +	key = strtok_r(NULL, "\t", &s);

- +

- +	/* XXX */

- +	if (strcmp(id, "anchor") == 0) {

- +	    id = "\x00\x00";

- +	    anchor = 1;

- +	}

- +

- +	st_logf("adding: %s\n", label);

- +

- +	add_certificate(label, cert, key, id, anchor);

- +    }

- +}

- +

- +static CK_RV

- +func_not_supported(void)

- +{

- +    st_logf("function not supported\n");

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_Initialize(CK_VOID_PTR a)

- +{

- +    CK_C_INITIALIZE_ARGS_PTR args = a;

- +    st_logf("Initialize\n");

- +    size_t i;

- +

- +    OpenSSL_add_all_algorithms();

- +    ERR_load_crypto_strings();

- +

- +    srandom(getpid() ^ time(NULL));

- +

- +    for (i = 0; i < MAX_NUM_SESSION; i++) {

- +	soft_token.state[i].session_handle = CK_INVALID_HANDLE;

- +	soft_token.state[i].find.attributes = NULL;

- +	soft_token.state[i].find.num_attributes = 0;

- +	soft_token.state[i].find.next_object = -1;

- +	reset_crypto_state(&soft_token.state[i]);

- +    }

- +

- +    soft_token.flags.hardware_slot = 1;

- +    soft_token.flags.app_error_fatal = 0;

- +    soft_token.flags.login_done = 0;

- +

- +    soft_token.object.objs = NULL;

- +    soft_token.object.num_objs = 0;

- +

- +    soft_token.logfile = NULL;

- +#if 1

- +//     soft_token.logfile = stdout;

- +#endif

- +#if 0

- +    soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");

- +#endif

- +

- +    if (a != NULL_PTR) {

- +	st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);

- +	st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);

- +	st_logf("\tLockMutext\t%p\n", args->LockMutex);

- +	st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);

- +	st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);

- +    }

- +

- +    {

- +	char *fn = NULL, *home = NULL;

- +

- +	if (getuid() == geteuid()) {

- +	    fn = getenv("SOFTPKCS11RC");

- +	    if (fn)

- +		fn = strdup(fn);

- +	    home = getenv("HOME");

- +	}

- +	if (fn == NULL && home == NULL) {

- +	    struct passwd *pw = getpwuid(getuid());	

- +	    if(pw != NULL)

- +		home = pw->pw_dir;

- +	}

- +	if (fn == NULL) {

- +	    if (home)

- +		asprintf(&fn, "%s/.soft-token.rc", home);

- +	    else

- +		fn = strdup("/etc/soft-token.rc");

- +	}

- +

- +	read_conf_file(fn);

- +	free(fn);

- +    }

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_Finalize(CK_VOID_PTR args)

- +{

- +    size_t i;

- +

- +    st_logf("Finalize\n");

- +

- +    for (i = 0; i < MAX_NUM_SESSION; i++) {

- +	if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {

- +	    application_error("application finalized without "

- +			      "closing session\n");

- +	    close_session(&soft_token.state[i]);

- +	}

- +    }

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_GetInfo(CK_INFO_PTR args)

- +{

- +    st_logf("GetInfo\n");

- +

- +    memset(args, 17, sizeof(*args));

- +    args->cryptokiVersion.major = 2;

- +    args->cryptokiVersion.minor = 10;

- +    snprintf_fill((char *)args->manufacturerID,

- +		  sizeof(args->manufacturerID),

- +		  ' ',

- +		  "SoftToken");

- +    snprintf_fill((char *)args->libraryDescription,

- +		  sizeof(args->libraryDescription), ' ',

- +		  "SoftToken");

- +    args->libraryVersion.major = 1;

- +    args->libraryVersion.minor = 8;

- +

- +    return CKR_OK;

- +}

- +

- +extern CK_FUNCTION_LIST funcs;

- +

- +CK_RV

- +C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)

- +{

- +    *ppFunctionList = &funcs;

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_GetSlotList(CK_BBOOL tokenPresent,

- +	      CK_SLOT_ID_PTR pSlotList,

- +	      CK_ULONG_PTR   pulCount)

- +{

- +    st_logf("GetSlotList: %s\n",

- +	    tokenPresent ? "tokenPresent" : "token not Present");

- +    if (pSlotList)

- +	pSlotList[0] = 1;

- +    *pulCount = 1;

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_GetSlotInfo(CK_SLOT_ID slotID,

- +	      CK_SLOT_INFO_PTR pInfo)

- +{

- +    st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());

- +

- +    memset(pInfo, 18, sizeof(*pInfo));

- +

- +    if (slotID != 1)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    snprintf_fill((char *)pInfo->slotDescription,

- +		  sizeof(pInfo->slotDescription),

- +		  ' ',

- +		  "SoftToken (slot)");

- +    snprintf_fill((char *)pInfo->manufacturerID,

- +		  sizeof(pInfo->manufacturerID),

- +		  ' ',

- +		  "SoftToken (slot)");

- +    pInfo->flags = CKF_TOKEN_PRESENT;

- +    if (soft_token.flags.hardware_slot)

- +	pInfo->flags |= CKF_HW_SLOT;

- +    pInfo->hardwareVersion.major = 1;

- +    pInfo->hardwareVersion.minor = 0;

- +    pInfo->firmwareVersion.major = 1;

- +    pInfo->firmwareVersion.minor = 0;

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_GetTokenInfo(CK_SLOT_ID slotID,

- +	       CK_TOKEN_INFO_PTR pInfo)

- +{

- +    st_logf("GetTokenInfo: %s\n", has_session());

- +

- +    memset(pInfo, 19, sizeof(*pInfo));

- +

- +    snprintf_fill((char *)pInfo->label,

- +		  sizeof(pInfo->label),

- +		  ' ',

- +		  "SoftToken (token)");

- +    snprintf_fill((char *)pInfo->manufacturerID,

- +		  sizeof(pInfo->manufacturerID),

- +		  ' ',

- +		  "SoftToken (token)");

- +    snprintf_fill((char *)pInfo->model,

- +		  sizeof(pInfo->model),

- +		  ' ',

- +		  "SoftToken (token)");

- +    snprintf_fill((char *)pInfo->serialNumber,

- +		  sizeof(pInfo->serialNumber),

- +		  ' ',

- +		  "4711");

- +    pInfo->flags =

- +	CKF_TOKEN_INITIALIZED |

- +	CKF_USER_PIN_INITIALIZED;

- +

- +    if (soft_token.flags.login_done == 0)

- +	pInfo->flags |= CKF_LOGIN_REQUIRED;

- +

- +    /* CFK_RNG |

- +       CKF_RESTORE_KEY_NOT_NEEDED |

- +    */

- +    pInfo->ulMaxSessionCount = MAX_NUM_SESSION;

- +    pInfo->ulSessionCount = soft_token.open_sessions;

- +    pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;

- +    pInfo->ulRwSessionCount = soft_token.open_sessions;

- +    pInfo->ulMaxPinLen = 1024;

- +    pInfo->ulMinPinLen = 0;

- +    pInfo->ulTotalPublicMemory = 4711;

- +    pInfo->ulFreePublicMemory = 4712;

- +    pInfo->ulTotalPrivateMemory = 4713;

- +    pInfo->ulFreePrivateMemory = 4714;

- +    pInfo->hardwareVersion.major = 2;

- +    pInfo->hardwareVersion.minor = 0;

- +    pInfo->firmwareVersion.major = 2;

- +    pInfo->firmwareVersion.minor = 0;

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_GetMechanismList(CK_SLOT_ID slotID,

- +		   CK_MECHANISM_TYPE_PTR pMechanismList,

- +		   CK_ULONG_PTR pulCount)

- +{

- +    st_logf("GetMechanismList\n");

- +

- +    *pulCount = 2;

- +    if (pMechanismList == NULL_PTR)

- +	return CKR_OK;

- +    pMechanismList[0] = CKM_RSA_X_509;

- +    pMechanismList[1] = CKM_RSA_PKCS;

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_GetMechanismInfo(CK_SLOT_ID slotID,

- +		   CK_MECHANISM_TYPE type,

- +		   CK_MECHANISM_INFO_PTR pInfo)

- +{

- +    st_logf("GetMechanismInfo: slot %d type: %d\n",

- +	    (int)slotID, (int)type);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_InitToken(CK_SLOT_ID slotID,

- +	    CK_UTF8CHAR_PTR pPin,

- +	    CK_ULONG ulPinLen,

- +	    CK_UTF8CHAR_PTR pLabel)

- +{

- +    st_logf("InitToken: slot %d\n", (int)slotID);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_OpenSession(CK_SLOT_ID slotID,

- +	      CK_FLAGS flags,

- +	      CK_VOID_PTR pApplication,

- +	      CK_NOTIFY Notify,

- +	      CK_SESSION_HANDLE_PTR phSession)

- +{

- +    size_t i;

- +

- +    st_logf("OpenSession: slot: %d\n", (int)slotID);

- +

- +    if (soft_token.open_sessions == MAX_NUM_SESSION)

- +	return CKR_SESSION_COUNT;

- +

- +    soft_token.application = pApplication;

- +    soft_token.notify = Notify;

- +

- +    for (i = 0; i < MAX_NUM_SESSION; i++)

- +	if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)

- +	    break;

- +    if (i == MAX_NUM_SESSION)

- +	abort();

- +

- +    soft_token.open_sessions++;

- +

- +    soft_token.state[i].session_handle =

- +	(CK_SESSION_HANDLE)(random() & 0xfffff);

- +    *phSession = soft_token.state[i].session_handle;

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_CloseSession(CK_SESSION_HANDLE hSession)

- +{

- +    struct session_state *state;

- +    st_logf("CloseSession\n");

- +

- +    if (verify_session_handle(hSession, &state) != CKR_OK)

- +	application_error("closed session not open");

- +    else

- +	close_session(state);

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_CloseAllSessions(CK_SLOT_ID slotID)

- +{

- +    size_t i;

- +

- +    st_logf("CloseAllSessions\n");

- +

- +    for (i = 0; i < MAX_NUM_SESSION; i++)

- +	if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)

- +	    close_session(&soft_token.state[i]);

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_GetSessionInfo(CK_SESSION_HANDLE hSession,

- +		 CK_SESSION_INFO_PTR pInfo)

- +{

- +    st_logf("GetSessionInfo\n");

- +

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +

- +    memset(pInfo, 20, sizeof(*pInfo));

- +

- +    pInfo->slotID = 1;

- +    if (soft_token.flags.login_done)

- +	pInfo->state = CKS_RO_USER_FUNCTIONS;

- +    else

- +	pInfo->state = CKS_RO_PUBLIC_SESSION;

- +    pInfo->flags = CKF_SERIAL_SESSION;

- +    pInfo->ulDeviceError = 0;

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_Login(CK_SESSION_HANDLE hSession,

- +	CK_USER_TYPE userType,

- +	CK_UTF8CHAR_PTR pPin,

- +	CK_ULONG ulPinLen)

- +{

- +    char *pin = NULL;

- +    int i;

- +

- +    st_logf("Login\n");

- +

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +

- +    if (pPin != NULL_PTR) {

- +	asprintf(&pin, "%.*s", (int)ulPinLen, pPin);

- +	st_logf("type: %d password: %s\n", (int)userType, pin);

- +    }

- +

- +    for (i = 0; i < soft_token.object.num_objs; i++) {

- +	struct st_object *o = soft_token.object.objs[i];

- +	FILE *f;

- +

- +	if (o->type != STO_T_PRIVATE_KEY)

- +	    continue;

- +

- +	if (o->u.private_key.key)

- +	    continue;

- +

- +	f = fopen(o->u.private_key.file, "r");

- +	if (f == NULL) {

- +	    st_logf("can't open private file: %s\n", o->u.private_key.file);

- +	    continue;

- +	}

- +	

- +	o->u.private_key.key = PEM_read_PrivateKey(f, NULL, NULL, pin);

- +	fclose(f);

- +	if (o->u.private_key.key == NULL) {

- +	    st_logf("failed to read key: %s error: %s\n",

- +		    o->u.private_key.file,

- +		    ERR_error_string(ERR_get_error(), NULL));

- +	    /* just ignore failure */;

- +	    continue;

- +	}

- +

- +	/* XXX check keytype */

- +	RSA *rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);

- +	RSA_set_method(rsa, RSA_PKCS1_OpenSSL());

- +

- +	if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) {

- +	    EVP_PKEY_free(o->u.private_key.key);

- +	    o->u.private_key.key = NULL;

- +	    st_logf("private key %s doesn't verify\n", o->u.private_key.file);

- +	    continue;

- +	}

- +

- +	soft_token.flags.login_done = 1;

- +    }

- +    free(pin);

- +

- +    return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;

- +}

- +

- +CK_RV

- +C_Logout(CK_SESSION_HANDLE hSession)

- +{

- +    st_logf("Logout\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_GetObjectSize(CK_SESSION_HANDLE hSession,

- +		CK_OBJECT_HANDLE hObject,

- +		CK_ULONG_PTR pulSize)

- +{

- +    st_logf("GetObjectSize\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_GetAttributeValue(CK_SESSION_HANDLE hSession,

- +		    CK_OBJECT_HANDLE hObject,

- +		    CK_ATTRIBUTE_PTR pTemplate,

- +		    CK_ULONG ulCount)

- +{

- +    struct session_state *state;

- +    struct st_object *obj;

- +    CK_ULONG i;

- +    CK_RV ret;

- +    int j;

- +

- +    st_logf("GetAttributeValue: %lx\n",

- +	    (unsigned long)HANDLE_OBJECT_ID(hObject));

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {

- +	st_logf("object not found: %lx\n",

- +		(unsigned long)HANDLE_OBJECT_ID(hObject));

- +	return ret;

- +    }

- +

- +    ret = CKR_OK;

- +    for (i = 0; i < ulCount; i++) {

- +	st_logf("	getting 0x%08lx\n", (unsigned long)pTemplate[i].type);

- +	for (j = 0; j < obj->num_attributes; j++) {

- +	    if (obj->attrs[j].secret) {

- +		pTemplate[i].ulValueLen = (CK_ULONG)-1;

- +		break;

- +	    }

- +	    if (pTemplate[i].type == obj->attrs[j].attribute.type) {

- +		if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {

- +		    if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)

- +			memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,

- +			       obj->attrs[j].attribute.ulValueLen);

- +		}

- +		pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;

- +		break;

- +	    }

- +	}

- +	if (j == obj->num_attributes) {

- +	    st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);

- +	    pTemplate[i].ulValueLen = (CK_ULONG)-1;

- +            ret = CKR_ATTRIBUTE_TYPE_INVALID;

- +	}

- +

- +    }

- +    return ret;

- +}

- +

- +CK_RV

- +C_FindObjectsInit(CK_SESSION_HANDLE hSession,

- +		  CK_ATTRIBUTE_PTR pTemplate,

- +		  CK_ULONG ulCount)

- +{

- +    struct session_state *state;

- +

- +    st_logf("FindObjectsInit\n");

- +

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    if (state->find.next_object != -1) {

- +	application_error("application didn't do C_FindObjectsFinal\n");

- +	find_object_final(state);

- +    }

- +    if (ulCount) {

- +	CK_ULONG i;

- +

- +	print_attributes(pTemplate, ulCount);

- +

- +	state->find.attributes =

- +	    calloc(1, ulCount * sizeof(state->find.attributes[0]));

- +	if (state->find.attributes == NULL)

- +	    return CKR_DEVICE_MEMORY;

- +	for (i = 0; i < ulCount; i++) {

- +	    state->find.attributes[i].pValue =

- +		malloc(pTemplate[i].ulValueLen);

- +	    if (state->find.attributes[i].pValue == NULL) {

- +		find_object_final(state);

- +		return CKR_DEVICE_MEMORY;

- +	    }

- +	    memcpy(state->find.attributes[i].pValue,

- +		   pTemplate[i].pValue, pTemplate[i].ulValueLen);

- +	    state->find.attributes[i].type = pTemplate[i].type;

- +	    state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;

- +	}

- +	state->find.num_attributes = ulCount;

- +	state->find.next_object = 0;

- +    } else {

- +	st_logf("find all objects\n");

- +	state->find.attributes = NULL;

- +	state->find.num_attributes = 0;

- +	state->find.next_object = 0;

- +    }

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_FindObjects(CK_SESSION_HANDLE hSession,

- +	      CK_OBJECT_HANDLE_PTR phObject,

- +	      CK_ULONG ulMaxObjectCount,

- +	      CK_ULONG_PTR pulObjectCount)

- +{

- +    struct session_state *state;

- +    int i;

- +

- +    st_logf("FindObjects\n");

- +

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    if (state->find.next_object == -1) {

- +	application_error("application didn't do C_FindObjectsInit\n");

- +	return CKR_ARGUMENTS_BAD;

- +    }

- +    if (ulMaxObjectCount == 0) {

- +	application_error("application asked for 0 objects\n");

- +	return CKR_ARGUMENTS_BAD;

- +    }

- +    *pulObjectCount = 0;

- +    for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {

- +	st_logf("FindObjects: %d\n", i);

- +	state->find.next_object = i + 1;

- +	if (attributes_match(soft_token.object.objs[i],

- +			     state->find.attributes,

- +			     state->find.num_attributes)) {

- +	    *phObject++ = soft_token.object.objs[i]->object_handle;

- +	    ulMaxObjectCount--;

- +	    (*pulObjectCount)++;

- +	    if (ulMaxObjectCount == 0)

- +		break;

- +	}

- +    }

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_FindObjectsFinal(CK_SESSION_HANDLE hSession)

- +{

- +    struct session_state *state;

- +

- +    st_logf("FindObjectsFinal\n");

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +    find_object_final(state);

- +    return CKR_OK;

- +}

- +

- +static CK_RV

- +commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,

- +	   const CK_MECHANISM_TYPE *mechs, int mechs_len,

- +	   const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,

- +	   struct st_object **o)

- +{

- +    CK_RV ret;

- +    int i;

- +

- +    *o = NULL;

- +    if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)

- +	return ret;

- +

- +    ret = attributes_match(*o, attr_match, attr_match_len);

- +    if (!ret) {

- +	application_error("called commonInit on key that doesn't "

- +			  "support required attr");

- +	return CKR_ARGUMENTS_BAD;

- +    }

- +

- +    for (i = 0; i < mechs_len; i++)

- +	if (mechs[i] == pMechanism->mechanism)

- +	    break;

- +    if (i == mechs_len) {

- +	application_error("called mech (%08lx) not supported\n",

- +			  pMechanism->mechanism);

- +	return CKR_ARGUMENTS_BAD;

- +    }

- +    return CKR_OK;

- +}

- +

- +

- +static CK_RV

- +dup_mechanism(CK_MECHANISM_PTR *dup, const CK_MECHANISM_PTR pMechanism)

- +{

- +    CK_MECHANISM_PTR p;

- +

- +    p = malloc(sizeof(*p));

- +    if (p == NULL)

- +	return CKR_DEVICE_MEMORY;

- +

- +    if (*dup)

- +	free(*dup);

- +    *dup = p;

- +    memcpy(p, pMechanism, sizeof(*p));

- +

- +    return CKR_OK;

- +}

- +

- +

- +CK_RV

- +C_EncryptInit(CK_SESSION_HANDLE hSession,

- +	      CK_MECHANISM_PTR pMechanism,

- +	      CK_OBJECT_HANDLE hKey)

- +{

- +    struct session_state *state;

- +    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };

- +    CK_BBOOL bool_true = CK_TRUE;

- +    CK_ATTRIBUTE attr[] = {

- +	{ CKA_ENCRYPT, &bool_true, sizeof(bool_true) }

- +    };

- +    struct st_object *o;

- +    CK_RV ret;

- +

- +    st_logf("EncryptInit\n");

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),

- +		     mechs, sizeof(mechs)/sizeof(mechs[0]),

- +		     pMechanism, hKey, &o);

- +    if (ret)

- +	return ret;

- +

- +    ret = dup_mechanism(&state->encrypt_mechanism, pMechanism);

- +    if (ret == CKR_OK)

- +	state->encrypt_object = OBJECT_ID(o);

- +			

- +    return ret;

- +}

- +

- +CK_RV

- +C_Encrypt(CK_SESSION_HANDLE hSession,

- +	  CK_BYTE_PTR pData,

- +	  CK_ULONG ulDataLen,

- +	  CK_BYTE_PTR pEncryptedData,

- +	  CK_ULONG_PTR pulEncryptedDataLen)

- +{

- +    struct session_state *state;

- +    struct st_object *o;

- +    void *buffer = NULL;

- +    CK_RV ret;

- +    RSA *rsa;

- +    int padding, len, buffer_len, padding_len;

- +

- +    st_logf("Encrypt\n");

- +

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    if (state->encrypt_object == -1)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    o = soft_token.object.objs[state->encrypt_object];

- +

- +    if (o->u.public_key == NULL) {

- +	st_logf("public key NULL\n");

- +	return CKR_ARGUMENTS_BAD;

- +    }

- +

- +    rsa = EVP_PKEY_get0_RSA(o->u.public_key);

- +    if (rsa == NULL)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */

- +

- +    buffer_len = RSA_size(rsa);

- +

- +    buffer = malloc(buffer_len);

- +    if (buffer == NULL) {

- +	ret = CKR_DEVICE_MEMORY;

- +	goto out;

- +    }

- +

- +    ret = CKR_OK;

- +    switch(state->encrypt_mechanism->mechanism) {

- +    case CKM_RSA_PKCS:

- +	padding = RSA_PKCS1_PADDING;

- +	padding_len = RSA_PKCS1_PADDING_SIZE;

- +	break;

- +    case CKM_RSA_X_509:

- +	padding = RSA_NO_PADDING;

- +	padding_len = 0;

- +	break;

- +    default:

- +	ret = CKR_FUNCTION_NOT_SUPPORTED;

- +	goto out;

- +    }

- +

- +    if (buffer_len + padding_len < (long) ulDataLen) {

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    if (pulEncryptedDataLen == NULL) {

- +	st_logf("pulEncryptedDataLen NULL\n");

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    if (pData == NULL_PTR) {

- +	st_logf("data NULL\n");

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    len = RSA_public_encrypt(ulDataLen, pData, buffer, rsa, padding);

- +    if (len <= 0) {

- +	ret = CKR_DEVICE_ERROR;

- +	goto out;

- +    }

- +    if (len > buffer_len)

- +	abort();

- +	

- +    if (pEncryptedData != NULL_PTR)

- +	memcpy(pEncryptedData, buffer, len);

- +    *pulEncryptedDataLen = len;

- +

- + out:

- +    if (buffer) {

- +	memset(buffer, 0, buffer_len);

- +	free(buffer);

- +    }

- +    return ret;

- +}

- +

- +CK_RV

- +C_EncryptUpdate(CK_SESSION_HANDLE hSession,

- +		CK_BYTE_PTR pPart,

- +		CK_ULONG ulPartLen,

- +		CK_BYTE_PTR pEncryptedPart,

- +		CK_ULONG_PTR pulEncryptedPartLen)

- +{

- +    st_logf("EncryptUpdate\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +

- +CK_RV

- +C_EncryptFinal(CK_SESSION_HANDLE hSession,

- +	       CK_BYTE_PTR pLastEncryptedPart,

- +	       CK_ULONG_PTR pulLastEncryptedPartLen)

- +{

- +    st_logf("EncryptFinal\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +

- +/* C_DecryptInit initializes a decryption operation. */

- +CK_RV

- +C_DecryptInit(CK_SESSION_HANDLE hSession,

- +	      CK_MECHANISM_PTR pMechanism,

- +	      CK_OBJECT_HANDLE hKey)

- +{

- +    struct session_state *state;

- +    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };

- +    CK_BBOOL bool_true = CK_TRUE;

- +    CK_ATTRIBUTE attr[] = {

- +	{ CKA_DECRYPT, &bool_true, sizeof(bool_true) }

- +    };

- +    struct st_object *o;

- +    CK_RV ret;

- +

- +    st_logf("DecryptInit\n");

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),

- +		     mechs, sizeof(mechs)/sizeof(mechs[0]),

- +		     pMechanism, hKey, &o);

- +    if (ret)

- +	return ret;

- +

- +    ret = dup_mechanism(&state->decrypt_mechanism, pMechanism);

- +    if (ret == CKR_OK)

- +	state->decrypt_object = OBJECT_ID(o);

- +

- +    return CKR_OK;

- +}

- +

- +

- +CK_RV

- +C_Decrypt(CK_SESSION_HANDLE hSession,

- +	  CK_BYTE_PTR       pEncryptedData,

- +	  CK_ULONG          ulEncryptedDataLen,

- +	  CK_BYTE_PTR       pData,

- +	  CK_ULONG_PTR      pulDataLen)

- +{

- +    struct session_state *state;

- +    struct st_object *o;

- +    void *buffer = NULL;

- +    CK_RV ret;

- +    RSA *rsa;

- +    int padding, len, buffer_len, padding_len;

- +

- +    st_logf("Decrypt\n");

- +

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    if (state->decrypt_object == -1)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    o = soft_token.object.objs[state->decrypt_object];

- +

- +    if (o->u.private_key.key == NULL) {

- +	st_logf("private key NULL\n");

- +	return CKR_ARGUMENTS_BAD;

- +    }

- +

- +    rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);

- +    if (rsa == NULL)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */

- +

- +    buffer_len = RSA_size(rsa);

- +

- +    buffer = malloc(buffer_len);

- +    if (buffer == NULL) {

- +	ret = CKR_DEVICE_MEMORY;

- +	goto out;

- +    }

- +

- +    ret = CKR_OK;

- +    switch(state->decrypt_mechanism->mechanism) {

- +    case CKM_RSA_PKCS:

- +	padding = RSA_PKCS1_PADDING;

- +	padding_len = RSA_PKCS1_PADDING_SIZE;

- +	break;

- +    case CKM_RSA_X_509:

- +	padding = RSA_NO_PADDING;

- +	padding_len = 0;

- +	break;

- +    default:

- +	ret = CKR_FUNCTION_NOT_SUPPORTED;

- +	goto out;

- +    }

- +

- +    if (buffer_len + padding_len < (long) ulEncryptedDataLen) {

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    if (pulDataLen == NULL) {

- +	st_logf("pulDataLen NULL\n");

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    if (pEncryptedData == NULL_PTR) {

- +	st_logf("data NULL\n");

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    len = RSA_private_decrypt(ulEncryptedDataLen, pEncryptedData, buffer,

- +			      rsa, padding);

- +    if (len <= 0) {

- +	ret = CKR_DEVICE_ERROR;

- +	goto out;

- +    }

- +    if (len > buffer_len)

- +	abort();

- +	

- +    if (pData != NULL_PTR)

- +	memcpy(pData, buffer, len);

- +    *pulDataLen = len;

- +

- + out:

- +    if (buffer) {

- +	memset(buffer, 0, buffer_len);

- +	free(buffer);

- +    }

- +    return ret;

- +}

- +

- +

- +CK_RV

- +C_DecryptUpdate(CK_SESSION_HANDLE hSession,

- +		CK_BYTE_PTR pEncryptedPart,

- +		CK_ULONG ulEncryptedPartLen,

- +		CK_BYTE_PTR pPart,

- +		CK_ULONG_PTR pulPartLen)

- +

- +{

- +    st_logf("DecryptUpdate\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +

- +CK_RV

- +C_DecryptFinal(CK_SESSION_HANDLE hSession,

- +	       CK_BYTE_PTR pLastPart,

- +	       CK_ULONG_PTR pulLastPartLen)

- +{

- +    st_logf("DecryptFinal\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_DigestInit(CK_SESSION_HANDLE hSession,

- +	     CK_MECHANISM_PTR pMechanism)

- +{

- +    st_logf("DigestInit\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_SignInit(CK_SESSION_HANDLE hSession,

- +	   CK_MECHANISM_PTR pMechanism,

- +	   CK_OBJECT_HANDLE hKey)

- +{

- +    struct session_state *state;

- +    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };

- +    CK_BBOOL bool_true = CK_TRUE;

- +    CK_ATTRIBUTE attr[] = {

- +	{ CKA_SIGN, &bool_true, sizeof(bool_true) }

- +    };

- +    struct st_object *o;

- +    CK_RV ret;

- +

- +    st_logf("SignInit\n");

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),

- +		     mechs, sizeof(mechs)/sizeof(mechs[0]),

- +		     pMechanism, hKey, &o);

- +    if (ret)

- +	return ret;

- +

- +    ret = dup_mechanism(&state->sign_mechanism, pMechanism);

- +    if (ret == CKR_OK)

- +	state->sign_object = OBJECT_ID(o);

- +

- +    return CKR_OK;

- +}

- +

- +CK_RV

- +C_Sign(CK_SESSION_HANDLE hSession,

- +       CK_BYTE_PTR pData,

- +       CK_ULONG ulDataLen,

- +       CK_BYTE_PTR pSignature,

- +       CK_ULONG_PTR pulSignatureLen)

- +{

- +    struct session_state *state;

- +    struct st_object *o;

- +    void *buffer = NULL;

- +    CK_RV ret;

- +    RSA *rsa;

- +    int padding, len, buffer_len;

- +    size_t padding_len;

- +

- +    st_logf("Sign\n");

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    if (state->sign_object == -1)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    o = soft_token.object.objs[state->sign_object];

- +

- +    if (o->u.private_key.key == NULL) {

- +	st_logf("private key NULL\n");

- +	return CKR_ARGUMENTS_BAD;

- +    }

- +

- +    rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);

- +    if (rsa == NULL)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */

- +

- +    buffer_len = RSA_size(rsa);

- +

- +    buffer = malloc(buffer_len);

- +    if (buffer == NULL) {

- +	ret = CKR_DEVICE_MEMORY;

- +	goto out;

- +    }

- +

- +    switch(state->sign_mechanism->mechanism) {

- +    case CKM_RSA_PKCS:

- +	padding = RSA_PKCS1_PADDING;

- +	padding_len = RSA_PKCS1_PADDING_SIZE;

- +	break;

- +    case CKM_RSA_X_509:

- +	padding = RSA_NO_PADDING;

- +	padding_len = 0;

- +	break;

- +    default:

- +	ret = CKR_FUNCTION_NOT_SUPPORTED;

- +	goto out;

- +    }

- +

- +    if ((size_t) buffer_len < ulDataLen + padding_len) {

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    if (pulSignatureLen == NULL) {

- +	st_logf("signature len NULL\n");

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    if (pData == NULL_PTR) {

- +	st_logf("data NULL\n");

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    len = RSA_private_encrypt(ulDataLen, pData, buffer, rsa, padding);

- +    st_logf("private encrypt done\n");

- +    if (len <= 0) {

- +	ret = CKR_DEVICE_ERROR;

- +	goto out;

- +    }

- +    if (len > buffer_len)

- +	abort();

- +	

- +    if (pSignature != NULL_PTR)

- +	memcpy(pSignature, buffer, len);

- +    *pulSignatureLen = len;

- +

- +    ret = CKR_OK;

- +

- + out:

- +    if (buffer) {

- +	memset(buffer, 0, buffer_len);

- +	free(buffer);

- +    }

- +    return ret;

- +}

- +

- +CK_RV

- +C_SignUpdate(CK_SESSION_HANDLE hSession,

- +	     CK_BYTE_PTR pPart,

- +	     CK_ULONG ulPartLen)

- +{

- +    st_logf("SignUpdate\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +

- +CK_RV

- +C_SignFinal(CK_SESSION_HANDLE hSession,

- +	    CK_BYTE_PTR pSignature,

- +	    CK_ULONG_PTR pulSignatureLen)

- +{

- +    st_logf("SignUpdate\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_VerifyInit(CK_SESSION_HANDLE hSession,

- +	     CK_MECHANISM_PTR pMechanism,

- +	     CK_OBJECT_HANDLE hKey)

- +{

- +    struct session_state *state;

- +    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };

- +    CK_BBOOL bool_true = CK_TRUE;

- +    CK_ATTRIBUTE attr[] = {

- +	{ CKA_VERIFY, &bool_true, sizeof(bool_true) }

- +    };

- +    struct st_object *o;

- +    CK_RV ret;

- +

- +    st_logf("VerifyInit\n");

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),

- +		     mechs, sizeof(mechs)/sizeof(mechs[0]),

- +		     pMechanism, hKey, &o);

- +    if (ret)

- +	return ret;

- +

- +    ret = dup_mechanism(&state->verify_mechanism, pMechanism);

- +    if (ret == CKR_OK)

- +	state->verify_object = OBJECT_ID(o);

- +			

- +    return ret;

- +}

- +

- +CK_RV

- +C_Verify(CK_SESSION_HANDLE hSession,

- +	 CK_BYTE_PTR pData,

- +	 CK_ULONG ulDataLen,

- +	 CK_BYTE_PTR pSignature,

- +	 CK_ULONG ulSignatureLen)

- +{

- +    struct session_state *state;

- +    struct st_object *o;

- +    void *buffer = NULL;

- +    CK_RV ret;

- +    RSA *rsa;

- +    int padding, len, buffer_len;

- +

- +    st_logf("Verify\n");

- +    VERIFY_SESSION_HANDLE(hSession, &state);

- +

- +    if (state->verify_object == -1)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    o = soft_token.object.objs[state->verify_object];

- +

- +    if (o->u.public_key == NULL) {

- +	st_logf("public key NULL\n");

- +	return CKR_ARGUMENTS_BAD;

- +    }

- +

- +    rsa = EVP_PKEY_get0_RSA(o->u.public_key);

- +    if (rsa == NULL)

- +	return CKR_ARGUMENTS_BAD;

- +

- +    RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */

- +

- +    buffer_len = RSA_size(rsa);

- +

- +    buffer = malloc(buffer_len);

- +    if (buffer == NULL) {

- +	ret = CKR_DEVICE_MEMORY;

- +	goto out;

- +    }

- +

- +    ret = CKR_OK;

- +    switch(state->verify_mechanism->mechanism) {

- +    case CKM_RSA_PKCS:

- +	padding = RSA_PKCS1_PADDING;

- +	break;

- +    case CKM_RSA_X_509:

- +	padding = RSA_NO_PADDING;

- +	break;

- +    default:

- +	ret = CKR_FUNCTION_NOT_SUPPORTED;

- +	goto out;

- +    }

- +

- +    if (buffer_len < (long) ulDataLen) {

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    if (pSignature == NULL) {

- +	st_logf("signature NULL\n");

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    if (pData == NULL_PTR) {

- +	st_logf("data NULL\n");

- +	ret = CKR_ARGUMENTS_BAD;

- +	goto out;

- +    }

- +

- +    len = RSA_public_decrypt(ulDataLen, pData, buffer, rsa, padding);

- +    st_logf("private encrypt done\n");

- +    if (len <= 0) {

- +	ret = CKR_DEVICE_ERROR;

- +	goto out;

- +    }

- +    if (len > buffer_len)

- +	abort();

- +	

- +    if ((size_t) len != ulSignatureLen) {

- +	ret = CKR_GENERAL_ERROR;

- +	goto out;

- +    }

- +	

- +    if (memcmp(pSignature, buffer, len) != 0) {

- +	ret = CKR_GENERAL_ERROR;

- +	goto out;

- +    }

- +

- + out:

- +    if (buffer) {

- +	memset(buffer, 0, buffer_len);

- +	free(buffer);

- +    }

- +    return ret;

- +}

- +

- +

- +CK_RV

- +C_VerifyUpdate(CK_SESSION_HANDLE hSession,

- +	       CK_BYTE_PTR pPart,

- +	       CK_ULONG ulPartLen)

- +{

- +    st_logf("VerifyUpdate\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_VerifyFinal(CK_SESSION_HANDLE hSession,

- +	      CK_BYTE_PTR pSignature,

- +	      CK_ULONG ulSignatureLen)

- +{

- +    st_logf("VerifyFinal\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +CK_RV

- +C_GenerateRandom(CK_SESSION_HANDLE hSession,

- +		 CK_BYTE_PTR RandomData,

- +		 CK_ULONG ulRandomLen)

- +{

- +    st_logf("GenerateRandom\n");

- +    VERIFY_SESSION_HANDLE(hSession, NULL);

- +    return CKR_FUNCTION_NOT_SUPPORTED;

- +}

- +

- +

- +CK_FUNCTION_LIST funcs = {

- +    { 2, 11 },

- +    C_Initialize,

- +    C_Finalize,

- +    C_GetInfo,

- +    C_GetFunctionList,

- +    C_GetSlotList,

- +    C_GetSlotInfo,

- +    C_GetTokenInfo,

- +    C_GetMechanismList,

- +    C_GetMechanismInfo,

- +    C_InitToken,

- +    (void *)func_not_supported, /* C_InitPIN */

- +    (void *)func_not_supported, /* C_SetPIN */

- +    C_OpenSession,

- +    C_CloseSession,

- +    C_CloseAllSessions,

- +    C_GetSessionInfo,

- +    (void *)func_not_supported, /* C_GetOperationState */

- +    (void *)func_not_supported, /* C_SetOperationState */

- +    C_Login,

- +    C_Logout,

- +    (void *)func_not_supported, /* C_CreateObject */

- +    (void *)func_not_supported, /* C_CopyObject */

- +    (void *)func_not_supported, /* C_DestroyObject */

- +    (void *)func_not_supported, /* C_GetObjectSize */

- +    C_GetAttributeValue,

- +    (void *)func_not_supported, /* C_SetAttributeValue */

- +    C_FindObjectsInit,

- +    C_FindObjects,

- +    C_FindObjectsFinal,

- +    C_EncryptInit,

- +    C_Encrypt,

- +    C_EncryptUpdate,

- +    C_EncryptFinal,

- +    C_DecryptInit,

- +    C_Decrypt,

- +    C_DecryptUpdate,

- +    C_DecryptFinal,

- +    C_DigestInit,

- +    (void *)func_not_supported, /* C_Digest */

- +    (void *)func_not_supported, /* C_DigestUpdate */

- +    (void *)func_not_supported, /* C_DigestKey */

- +    (void *)func_not_supported, /* C_DigestFinal */

- +    C_SignInit,

- +    C_Sign,

- +    C_SignUpdate,

- +    C_SignFinal,

- +    (void *)func_not_supported, /* C_SignRecoverInit */

- +    (void *)func_not_supported, /* C_SignRecover */

- +    C_VerifyInit,

- +    C_Verify,

- +    C_VerifyUpdate,

- +    C_VerifyFinal,

- +    (void *)func_not_supported, /* C_VerifyRecoverInit */

- +    (void *)func_not_supported, /* C_VerifyRecover */

- +    (void *)func_not_supported, /* C_DigestEncryptUpdate */

- +    (void *)func_not_supported, /* C_DecryptDigestUpdate */

- +    (void *)func_not_supported, /* C_SignEncryptUpdate */

- +    (void *)func_not_supported, /* C_DecryptVerifyUpdate */

- +    (void *)func_not_supported, /* C_GenerateKey */

- +    (void *)func_not_supported, /* C_GenerateKeyPair */

- +    (void *)func_not_supported, /* C_WrapKey */

- +    (void *)func_not_supported, /* C_UnwrapKey */

- +    (void *)func_not_supported, /* C_DeriveKey */

- +    (void *)func_not_supported, /* C_SeedRandom */

- +    C_GenerateRandom,

- +    (void *)func_not_supported, /* C_GetFunctionStatus */

- +    (void *)func_not_supported, /* C_CancelFunction */

- +    (void *)func_not_supported  /* C_WaitForSlotEvent */

- +};

- diff -up openssh/regress/unittests/Makefile.pkcs11-uri openssh/regress/unittests/Makefile

- --- openssh/regress/unittests/Makefile.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/regress/unittests/Makefile	2018-10-12 13:52:55.453191425 +0200

- @@ -2,6 +2,6 @@

-  

-  REGRESS_FAIL_EARLY?=	yes

-  SUBDIR=	test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion

- -SUBDIR+=authopt

- +SUBDIR+=pkcs11 authopt

-  

-  .include <bsd.subdir.mk>

- diff -up openssh/regress/unittests/pkcs11/Makefile.pkcs11-uri openssh/regress/unittests/pkcs11/Makefile

- --- openssh/regress/unittests/pkcs11/Makefile.pkcs11-uri	2018-10-12 13:52:55.453191425 +0200

- +++ openssh/regress/unittests/pkcs11/Makefile	2018-10-12 13:52:55.453191425 +0200

- @@ -0,0 +1,9 @@

- +

- +PROG=test_pkcs11

- +SRCS=tests.c

- +REGRESS_TARGETS=run-regress-${PROG}

- +

- +run-regress-${PROG}: ${PROG}

- +	env ${TEST_ENV} ./${PROG}

- +

- +.include <bsd.regress.mk>

- diff -up openssh/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh/regress/unittests/pkcs11/tests.c

- --- openssh/regress/unittests/pkcs11/tests.c.pkcs11-uri	2018-10-12 13:52:55.453191425 +0200

- +++ openssh/regress/unittests/pkcs11/tests.c	2018-10-12 13:52:55.453191425 +0200

- @@ -0,0 +1,330 @@

- +/*

- + * Copyright (c) 2017 Red Hat

- + *

- + * Authors: Jakub Jelen <jjelen@redhat.com>

- + *

- + * Permission to use, copy, modify, and distribute this software for any

- + * purpose with or without fee is hereby granted, provided that the above

- + * copyright notice and this permission notice appear in all copies.

- + *

- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES

- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF

- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR

- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES

- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN

- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF

- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

- + */

- +

- +#include "includes.h"

- +

- +#include <locale.h>

- +#include <string.h>

- +

- +#include "../test_helper/test_helper.h"

- +

- +#include "sshbuf.h"

- +#include "ssh-pkcs11-uri.h"

- +

- +#define EMPTY_URI compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL)

- +

- +/* prototypes are not public -- specify them here internally for tests */

- +struct sshbuf *percent_encode(const char *, size_t, char *);

- +int percent_decode(char *, char **);

- +

- +void

- +compare_uri(struct pkcs11_uri *a, struct pkcs11_uri *b)

- +{

- +	ASSERT_PTR_NE(a, NULL);

- +	ASSERT_PTR_NE(b, NULL);

- +	ASSERT_SIZE_T_EQ(a->id_len, b->id_len);

- +	ASSERT_MEM_EQ(a->id, b->id, a->id_len);

- +	if (b->object != NULL)

- +		ASSERT_STRING_EQ(a->object, b->object);

- +	else /* both should be null */

- +		ASSERT_PTR_EQ(a->object, b->object);

- +	if (b->module_path != NULL)

- +		ASSERT_STRING_EQ(a->module_path, b->module_path);

- +	else /* both should be null */

- +		ASSERT_PTR_EQ(a->module_path, b->module_path);

- +	if (b->token != NULL)

- +		ASSERT_STRING_EQ(a->token, b->token);

- +	else /* both should be null */

- +		ASSERT_PTR_EQ(a->token, b->token);

- +	if (b->manuf != NULL)

- +		ASSERT_STRING_EQ(a->manuf, b->manuf);

- +	else /* both should be null */

- +		ASSERT_PTR_EQ(a->manuf, b->manuf);

- +	if (b->lib_manuf != NULL)

- +		ASSERT_STRING_EQ(a->lib_manuf, b->lib_manuf);

- +	else /* both should be null */

- +		ASSERT_PTR_EQ(a->lib_manuf, b->lib_manuf);

- +}

- +

- +void

- +check_parse_rv(char *uri, struct pkcs11_uri *expect, int expect_rv)

- +{

- +	char *buf = NULL, *str;

- +	struct pkcs11_uri *pkcs11uri = NULL;

- +	int rv;

- +

- +	if (expect_rv == 0)

- +		str = "Valid";

- +	else

- +		str = "Invalid";

- +	asprintf(&buf, "%s PKCS#11 URI parsing: %s", str, uri);

- +	TEST_START(buf);

- +	free(buf);

- +	pkcs11uri = pkcs11_uri_init();

- +	rv = pkcs11_uri_parse(uri, pkcs11uri);

- +	ASSERT_INT_EQ(rv, expect_rv);

- +	if (rv == 0) /* in case of failure result is undefined */

- +		compare_uri(pkcs11uri, expect);

- +	pkcs11_uri_cleanup(pkcs11uri);

- +	free(expect);

- +	TEST_DONE();

- +}

- +

- +void

- +check_parse(char *uri, struct pkcs11_uri *expect)

- +{

- +	check_parse_rv(uri, expect, 0);

- +}

- +

- +struct pkcs11_uri *

- +compose_uri(unsigned char *id, size_t id_len, char *token, char *lib_manuf,

- +    char *manuf, char *module_path, char *object)

- +{

- +	struct pkcs11_uri *uri = pkcs11_uri_init();

- +	if (id_len > 0) {

- +		uri->id_len = id_len;

- +		uri->id = id;

- +	}

- +	uri->module_path = module_path;

- +	uri->token = token;

- +	uri->lib_manuf = lib_manuf;

- +	uri->manuf = manuf;

- +	uri->object = object;

- +	return uri;

- +}

- +

- +static void

- +test_parse_valid(void)

- +{

- +	/* path arguments */

- +	check_parse("pkcs11:id=%01",

- +	    compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL));

- +	check_parse("pkcs11:id=%00%01",

- +	    compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL));

- +	check_parse("pkcs11:token=SSH%20Keys",

- +	    compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL));

- +	check_parse("pkcs11:library-manufacturer=OpenSC",

- +	    compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL));

- +	check_parse("pkcs11:manufacturer=piv_II",

- +	    compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL));

- +	check_parse("pkcs11:object=SIGN%20Key",

- +	    compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "SIGN Key"));

- +	/* query arguments */

- +	check_parse("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so",

- +	    compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL));

- +

- +	/* combinations */

- +	/* ID SHOULD be percent encoded */

- +	check_parse("pkcs11:token=SSH%20Key;id=0",

- +	    compose_uri("0", 1, "SSH Key", NULL, NULL, NULL, NULL));

- +	check_parse(

- +	    "pkcs11:manufacturer=CAC?module-path=/usr/lib64/p11-kit-proxy.so",

- +	    compose_uri(NULL, 0, NULL, NULL, "CAC",

- +	    "/usr/lib64/p11-kit-proxy.so", NULL));

- +	check_parse(

- +	    "pkcs11:object=RSA%20Key?module-path=/usr/lib64/pkcs11/opencryptoki.so",

- +	    compose_uri(NULL, 0, NULL, NULL, NULL,

- +	    "/usr/lib64/pkcs11/opencryptoki.so", "RSA Key"));

- +

- +	/* empty path component matches everything */

- +	check_parse("pkcs11:", EMPTY_URI);

- +

- +	/* empty string is a valid to match against (and different from NULL) */

- +	check_parse("pkcs11:token=",

- +	    compose_uri(NULL, 0, "", NULL, NULL, NULL, NULL));

- +	/* Percent character needs to be percent-encoded */

- +	check_parse("pkcs11:token=%25",

- +	     compose_uri(NULL, 0, "%", NULL, NULL, NULL, NULL));

- +}

- +

- +static void

- +test_parse_invalid(void)

- +{

- +	/* Invalid percent encoding */

- +	check_parse_rv("pkcs11:id=%0", EMPTY_URI, -1);

- +	/* Invalid percent encoding */

- +	check_parse_rv("pkcs11:id=%ZZ", EMPTY_URI, -1);

- +	/* Space MUST be percent encoded -- XXX not enforced yet */

- +	check_parse("pkcs11:token=SSH Keys",

- +	    compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL));

- +	/* MUST NOT contain duplicate attributes of the same name */

- +	check_parse_rv("pkcs11:id=%01;id=%02", EMPTY_URI, -1);

- +	/* Unrecognized attribute in path are ignored with log message */

- +	check_parse("pkcs11:key_name=SSH", EMPTY_URI);

- +	/* Unrecognized attribute in query SHOULD be ignored */

- +	check_parse("pkcs11:?key_name=SSH", EMPTY_URI);

- +}

- +

- +void

- +check_gen(char *expect, struct pkcs11_uri *uri)

- +{

- +	char *buf = NULL, *uri_str;

- +

- +	asprintf(&buf, "Valid PKCS#11 URI generation: %s", expect);

- +	TEST_START(buf);

- +	free(buf);

- +	uri_str = pkcs11_uri_get(uri);

- +	ASSERT_PTR_NE(uri_str, NULL);

- +	ASSERT_STRING_EQ(uri_str, expect);

- +	free(uri_str);

- +	TEST_DONE();

- +}

- +

- +static void

- +test_generate_valid(void)

- +{

- +	/* path arguments */

- +	check_gen("pkcs11:id=%01",

- +	    compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL));

- +	check_gen("pkcs11:id=%00%01",

- +	    compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL));

- +	check_gen("pkcs11:token=SSH%20Keys", /* space must be percent encoded */

- +	    compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL));

- +	/* library-manufacturer is not implmented now */

- +	/*check_gen("pkcs11:library-manufacturer=OpenSC",

- +	    compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL));*/

- +	check_gen("pkcs11:manufacturer=piv_II",

- +	    compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL));

- +	check_gen("pkcs11:object=RSA%20Key",

- +	    compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "RSA Key"));

- +	/* query arguments */

- +	check_gen("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so",

- +	    compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL));

- +

- +	/* combinations */

- +	check_gen("pkcs11:id=%02;token=SSH%20Keys",

- +	    compose_uri("\x02", 1, "SSH Keys", NULL, NULL, NULL, NULL));

- +	check_gen("pkcs11:id=%EE%02?module-path=/usr/lib64/p11-kit-proxy.so",

- +	    compose_uri("\xEE\x02", 2, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL));

- +	check_gen("pkcs11:object=Encryption%20Key;manufacturer=piv_II",

- +	    compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, "Encryption Key"));

- +

- +	/* empty path component matches everything */

- +	check_gen("pkcs11:", EMPTY_URI);

- +

- +}

- +

- +void

- +check_encode(char *source, size_t len, char *whitelist, char *expect)

- +{

- +	char *buf = NULL;

- +	struct sshbuf *b;

- +

- +	asprintf(&buf, "percent_encode: expected %s", expect);

- +	TEST_START(buf);

- +	free(buf);

- +

- +	b = percent_encode(source, len, whitelist);

- +	ASSERT_STRING_EQ(sshbuf_ptr(b), expect);

- +	sshbuf_free(b);

- +	TEST_DONE();

- +}

- +

- +static void

- +test_percent_encode_multibyte(void)

- +{

- +	/* SHOULD be encoded as octets according to the UTF-8 character encoding */

- +

- +	/* multi-byte characters are "for free" */

- +	check_encode("$", 1, "", "%24");

- +	check_encode("¢", 2, "", "%C2%A2");

- +	check_encode("€", 3, "", "%E2%82%AC");

- +	check_encode("𐍈", 4, "", "%F0%90%8D%88");

- +

- +	/* CK_UTF8CHAR is unsigned char (1 byte) */

- +	/* labels SHOULD be normalized to NFC [UAX15] */

- +

- +}

- +

- +static void

- +test_percent_encode(void)

- +{

- +	/* Without whitelist encodes everything (for CKA_ID) */

- +	check_encode("A*", 2, "", "%41%2A");

- +	check_encode("\x00", 1, "", "%00");

- +	check_encode("\x7F", 1, "", "%7F");

- +	check_encode("\x80", 1, "", "%80");

- +	check_encode("\xff", 1, "", "%FF");

- +

- +	/* Default whitelist encodes anything but safe letters */

- +	check_encode("test" "\x00" "0alpha", 11, PKCS11_URI_WHITELIST,

- +	    "test%000alpha");

- +	check_encode(" ", 1, PKCS11_URI_WHITELIST,

- +	    "%20"); /* Space MUST be percent encoded */

- +	check_encode("/", 1, PKCS11_URI_WHITELIST,

- +	    "%2F"); /* '/' delimiter MUST be percent encoded (in the path) */

- +	check_encode("?", 1, PKCS11_URI_WHITELIST,

- +	    "%3F"); /* delimiter '?' MUST be percent encoded (in the path) */

- +	check_encode("#", 1, PKCS11_URI_WHITELIST,

- +	    "%23"); /* '#' MUST be always percent encoded */

- +	check_encode("key=value;separator?query&amp;#anch", 35, PKCS11_URI_WHITELIST,

- +	    "key%3Dvalue%3Bseparator%3Fquery%26amp%3B%23anch");

- +

- +	/* Components in query can have '/' unencoded (useful for paths) */

- +	check_encode("/path/to.file", 13, PKCS11_URI_WHITELIST "/",

- +	    "/path/to.file");

- +}

- +

- +void

- +check_decode(char *source, char *expect, int expect_len)

- +{

- +	char *buf = NULL, *out = NULL;

- +	int rv;

- +

- +	asprintf(&buf, "percent_decode: %s", source);

- +	TEST_START(buf);

- +	free(buf);

- +

- +	rv = percent_decode(source, &out);

- +	ASSERT_INT_EQ(rv, expect_len);

- +	if (rv >= 0)

- +		ASSERT_MEM_EQ(out, expect, expect_len);

- +	free(out);

- +	TEST_DONE();

- +}

- +

- +static void

- +test_percent_decode(void)

- +{

- +	/* simple valid cases */

- +	check_decode("%00", "\x00", 1);

- +	check_decode("%FF", "\xFF", 1);

- +

- +	/* normal strings shold be kept intact */

- +	check_decode("strings are left", "strings are left", 16);

- +	check_decode("10%25 of trees", "10% of trees", 12);

- +

- +	/* make sure no more than 2 bytes are parsed */

- +	check_decode("%222", "\x22" "2", 2);

- +

- +	/* invalid expects failure */

- +	check_decode("%0", "", -1);

- +	check_decode("%Z", "", -1);

- +	check_decode("%FG", "", -1);

- +}

- +

- +void

- +tests(void)

- +{

- +	test_percent_encode();

- +	test_percent_encode_multibyte();

- +	test_percent_decode();

- +	test_parse_valid();

- +	test_parse_invalid();

- +	test_generate_valid();

- +}

- diff -up openssh/ssh-add.c.pkcs11-uri openssh/ssh-add.c

- --- openssh/ssh-add.c.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/ssh-add.c	2018-10-12 13:52:55.454191434 +0200

- @@ -64,6 +64,7 @@

-  #include "misc.h"

-  #include "ssherr.h"

-  #include "digest.h"

- +#include "ssh-pkcs11-uri.h"

-  

-  /* argv0 */

-  extern char *__progname;

- @@ -188,6 +189,24 @@ delete_all(int agent_fd, int qflag)

-  	return ret;

-  }

-  

- +#ifdef ENABLE_PKCS11

- +static int update_card(int, int, const char *, int);

- +

- +int

- +update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag)

- +{

- +	struct pkcs11_uri *uri;

- +

- +	/* dry-run parse to make sure the URI is valid and to report errors */

- +	uri = pkcs11_uri_init();

- +	if (pkcs11_uri_parse((char *) pkcs11_uri, uri) != 0)

- +		fatal("Failed to parse PKCS#11 URI");

- +	pkcs11_uri_cleanup(uri);

- +

- +	return update_card(agent_fd, adding, pkcs11_uri, qflag);

- +}

- +#endif

- +

-  static int

-  add_file(int agent_fd, const char *filename, int key_only, int qflag)

-  {

- @@ -495,6 +514,13 @@ lock_agent(int agent_fd, int lock)

-  static int

-  do_file(int agent_fd, int deleting, int key_only, char *file, int qflag)

-  {

- +#ifdef ENABLE_PKCS11

- +	if (strlen(file) >= strlen(PKCS11_URI_SCHEME) &&

- +	    strncmp(file, PKCS11_URI_SCHEME,

- +	    strlen(PKCS11_URI_SCHEME)) == 0) {

- +		return update_pkcs11_uri(agent_fd, !deleting, file, qflag);

- +	}

- +#endif

-  	if (deleting) {

-  		if (delete_file(agent_fd, file, key_only, qflag) == -1)

-  			return -1;

- diff -up openssh/ssh-agent.c.pkcs11-uri openssh/ssh-agent.c

- --- openssh/ssh-agent.c.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/ssh-agent.c	2018-10-12 13:52:55.454191434 +0200

- @@ -546,10 +546,72 @@ no_identities(SocketEntry *e)

-  }

-  

-  #ifdef ENABLE_PKCS11

- +static char *

- +sanitize_pkcs11_provider(const char *provider)

- +{

- +	struct pkcs11_uri *uri = NULL;

- +	char *sane_uri, *module_path = NULL; /* default path */

- +	char canonical_provider[PATH_MAX];

- +

- +	if (provider == NULL)

- +		return NULL;

- +

- +	if (strlen(provider) >= strlen(PKCS11_URI_SCHEME) &&

- +	    strncmp(provider, PKCS11_URI_SCHEME,

- +	    strlen(PKCS11_URI_SCHEME)) == 0) {

- +		/* PKCS#11 URI */

- +		uri = pkcs11_uri_init();

- +		if (uri == NULL) {

- +			error("Failed to init PCKS#11 URI");

- +			return NULL;

- +		}

- +

- +		if (pkcs11_uri_parse(provider, uri) != 0) {

- +			error("Failed to parse PKCS#11 URI");

- +			return NULL;

- +		}

- +		/* validate also provider from URI */

- +		if (uri->module_path)

- +			module_path = strdup(uri->module_path);

- +	} else

- +		module_path = strdup(provider); /* simple path */

- +

- +	if (module_path != NULL) { /* do not validate default NULL path in URI */

- +		if (realpath(module_path, canonical_provider) == NULL) {

- +			verbose("failed PKCS#11 provider \"%.100s\": realpath: %s",

- +			    module_path, strerror(errno));

- +			free(module_path);

- +			pkcs11_uri_cleanup(uri);

- +			return NULL;

- +		}

- +		free(module_path);

- +		if (match_pattern_list(canonical_provider, pkcs11_whitelist, 0) != 1) {

- +			verbose("refusing PKCS#11 provider \"%.100s\": "

- +			    "not whitelisted", canonical_provider);

- +			pkcs11_uri_cleanup(uri);

- +			return NULL;

- +		}

- +

- +		/* copy verified and sanitized provider path back to the uri */

- +		if (uri) {

- +			free(uri->module_path);

- +			uri->module_path = xstrdup(canonical_provider);

- +		}

- +	}

- +

- +	if (uri) {

- +		sane_uri = pkcs11_uri_get(uri);

- +		pkcs11_uri_cleanup(uri);

- +		return sane_uri;

- +	} else {

- +		return xstrdup(canonical_provider); /* simple path */

- +	}

- +}

- +

-  static void

-  process_add_smartcard_key(SocketEntry *e)

-  {

- -	char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];

- +	char *provider = NULL, *pin = NULL, *sane_uri = NULL;

-  	int r, i, count = 0, success = 0, confirm = 0;

-  	u_int seconds;

-  	time_t death = 0;

- @@ -585,28 +647,23 @@ process_add_smartcard_key(SocketEntry *e

-  			goto send;

-  		}

-  	}

- -	if (realpath(provider, canonical_provider) == NULL) {

- -		verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",

- -		    provider, strerror(errno));

- -		goto send;

- -	}

- -	if (match_pattern_list(canonical_provider, pkcs11_whitelist, 0) != 1) {

- -		verbose("refusing PKCS#11 add of \"%.100s\": "

- -		    "provider not whitelisted", canonical_provider);

- +

- +	sane_uri = sanitize_pkcs11_provider(provider);

- +	if (sane_uri == NULL)

-  		goto send;

- -	}

- -	debug("%s: add %.100s", __func__, canonical_provider);

- +

-  	if (lifetime && !death)

-  		death = monotime() + lifetime;

-  

- -	count = pkcs11_add_provider(canonical_provider, pin, &keys);

- +	debug("%s: add %.100s", __func__, sane_uri);

- +	count = pkcs11_add_provider(sane_uri, pin, &keys);

-  	for (i = 0; i < count; i++) {

-  		k = keys[i];

-  		if (lookup_identity(k) == NULL) {

-  			id = xcalloc(1, sizeof(Identity));

-  			id->key = k;

- -			id->provider = xstrdup(canonical_provider);

- -			id->comment = xstrdup(canonical_provider); /* XXX */

- +			id->provider = xstrdup(sane_uri);

- +			id->comment = xstrdup(sane_uri);

-  			id->death = death;

-  			id->confirm = confirm;

-  			TAILQ_INSERT_TAIL(&idtab->idlist, id, next);

- @@ -620,6 +677,7 @@ process_add_smartcard_key(SocketEntry *e

-  send:

-  	free(pin);

-  	free(provider);

- +	free(sane_uri);

-  	free(keys);

-  	send_status(e, success);

-  }

- @@ -627,7 +685,7 @@ send:

-  static void

-  process_remove_smartcard_key(SocketEntry *e)

-  {

- -	char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];

- +	char *provider = NULL, *pin = NULL, *sane_uri = NULL;

-  	int r, success = 0;

-  	Identity *id, *nxt;

-  

- @@ -638,30 +696,29 @@ process_remove_smartcard_key(SocketEntry

-  	}

-  	free(pin);

-  

- -	if (realpath(provider, canonical_provider) == NULL) {

- -		verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",

- -		    provider, strerror(errno));

- +	sane_uri = sanitize_pkcs11_provider(provider);

- +	if (sane_uri == NULL)

-  		goto send;

- -	}

-  

- -	debug("%s: remove %.100s", __func__, canonical_provider);

- +	debug("%s: remove %.100s", __func__, sane_uri);

-  	for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {

-  		nxt = TAILQ_NEXT(id, next);

-  		/* Skip file--based keys */

-  		if (id->provider == NULL)

-  			continue;

- -		if (!strcmp(canonical_provider, id->provider)) {

- +		if (!strcmp(sane_uri, id->provider)) {

-  			TAILQ_REMOVE(&idtab->idlist, id, next);

-  			free_identity(id);

-  			idtab->nentries--;

-  		}

-  	}

- -	if (pkcs11_del_provider(canonical_provider) == 0)

- +	if (pkcs11_del_provider(sane_uri) == 0)

-  		success = 1;

-  	else

-  		error("%s: pkcs11_del_provider failed", __func__);

-  send:

-  	free(provider);

- +	free(sane_uri);

-  	send_status(e, success);

-  }

-  #endif /* ENABLE_PKCS11 */

- diff -up openssh/ssh_config.5.pkcs11-uri openssh/ssh_config.5

- --- openssh/ssh_config.5.pkcs11-uri	2018-10-12 13:52:55.437191293 +0200

- +++ openssh/ssh_config.5	2018-10-12 13:52:55.459191475 +0200

- @@ -991,6 +991,19 @@ may also be used in conjunction with

-  .Cm CertificateFile

-  in order to provide any certificate also needed for authentication with

-  the identity.

- +.Pp

- +The authentication identity can be also specified in a form of PKCS#11 URI

- +starting with a string

- +.Cm pkcs11: .

- +There is supported a subset of the PKCS#11 URI as defined

- +in RFC 7512 (implemented path arguments

- +.Cm id ,

- +.Cm manufacturer ,

- +.Cm object ,

- +.Cm token

- +and query argument

- +.Cm module-path

- +). The URI can not be in quotes.

-  .It Cm IgnoreUnknown

-  Specifies a pattern-list of unknown options to be ignored if they are

-  encountered in configuration parsing.

- diff -up openssh/ssh.c.pkcs11-uri openssh/ssh.c

- --- openssh/ssh.c.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/ssh.c	2018-10-12 13:52:55.458191467 +0200

- @@ -769,6 +769,14 @@ main(int ac, char **av)

-  			options.gss_deleg_creds = 1;

-  			break;

-  		case 'i':

- +#ifdef ENABLE_PKCS11

- +			if (strlen(optarg) >= strlen(PKCS11_URI_SCHEME) &&

- +			    strncmp(optarg, PKCS11_URI_SCHEME,

- +			    strlen(PKCS11_URI_SCHEME)) == 0) {

- +				add_identity_file(&options, NULL, optarg, 1);

- +				break;

- +			}

- +#endif

-  			p = tilde_expand_filename(optarg, getuid());

-  			if (stat(p, &st) < 0)

-  				fprintf(stderr, "Warning: Identity file %s "

- @@ -1975,6 +1983,45 @@ ssh_session2(struct ssh *ssh, struct pas

-  	    options.escape_char : SSH_ESCAPECHAR_NONE, id);

-  }

-  

- +#ifdef ENABLE_PKCS11

- +static void

- +load_pkcs11_identity(char *pkcs11_uri, char *identity_files[],

- +    struct sshkey *identity_keys[], int *n_ids)

- +{

- +	int nkeys, i;

- +	struct sshkey **keys;

- +	struct pkcs11_uri *uri;

- +

- +	debug("identity file '%s' from pkcs#11", pkcs11_uri);

- +	uri = pkcs11_uri_init();

- +	if (uri == NULL)

- +		fatal("Failed to init PCKS#11 URI");

- +

- +	if (pkcs11_uri_parse(pkcs11_uri, uri) != 0)

- +	fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri);

- +

- +	/* we need to merge URI and provider together */

- +	if (options.pkcs11_provider != NULL && uri->module_path == NULL)

- +		uri->module_path = strdup(options.pkcs11_provider);

- +

- +	if (options.num_identity_files < SSH_MAX_IDENTITY_FILES &&

- +	    (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys)) > 0) {

- +		for (i = 0; i < nkeys; i++) {

- +			if (*n_ids >= SSH_MAX_IDENTITY_FILES) {

- +				sshkey_free(keys[i]);

- +				continue;

- +			}

- +			identity_keys[*n_ids] = keys[i];

- +			identity_files[*n_ids] = pkcs11_uri_get(uri);

- +			(*n_ids)++;

- +		}

- +		free(keys);

- +	}

- +

- +	pkcs11_uri_cleanup(uri);

- +}

- +#endif /* ENABLE_PKCS11 */

- +

-  /* Loads all IdentityFile and CertificateFile keys */

-  static void

-  load_public_identity_files(struct passwd *pw)

- @@ -1989,10 +2036,6 @@ load_public_identity_files(struct passwd

-  	char *certificate_files[SSH_MAX_CERTIFICATE_FILES];

-  	struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];

-  	int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];

- -#ifdef ENABLE_PKCS11

- -	struct sshkey **keys;

- -	int nkeys;

- -#endif /* PKCS11 */

-  

-  	n_ids = n_certs = 0;

-  	memset(identity_files, 0, sizeof(identity_files));

- @@ -2005,32 +2048,46 @@ load_public_identity_files(struct passwd

-  	    sizeof(certificate_file_userprovided));

-  

-  #ifdef ENABLE_PKCS11

- -	if (options.pkcs11_provider != NULL &&

- -	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&

- -	    (pkcs11_init(!options.batch_mode) == 0) &&

- -	    (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,

- -	    &keys)) > 0) {

- -		for (i = 0; i < nkeys; i++) {

- -			if (n_ids >= SSH_MAX_IDENTITY_FILES) {

- -				sshkey_free(keys[i]);

- -				continue;

- -			}

- -			identity_keys[n_ids] = keys[i];

- -			identity_files[n_ids] =

- -			    xstrdup(options.pkcs11_provider); /* XXX */

- -			n_ids++;

- -		}

- -		free(keys);

- +	/* handle fallback from PKCS11Provider option */

- +	pkcs11_init(!options.batch_mode);

- +

- +	if (options.pkcs11_provider != NULL) {

- +		struct pkcs11_uri *uri;

- +

- +		uri = pkcs11_uri_init();

- +		if (uri == NULL)

- +			fatal("Failed to init PCKS#11 URI");

- +

- +		/* Construct simple PKCS#11 URI to simplify access */

- +		uri->module_path = strdup(options.pkcs11_provider);

- +

- +		/* Add it as any other IdentityFile */

- +		cp = pkcs11_uri_get(uri);

- +		add_identity_file(&options, NULL, cp, 1);

- +		free(cp);

- +

- +		pkcs11_uri_cleanup(uri);

-  	}

-  #endif /* ENABLE_PKCS11 */

-  	for (i = 0; i < options.num_identity_files; i++) {

- +		char *name = options.identity_files[i];

-  		if (n_ids >= SSH_MAX_IDENTITY_FILES ||

- -		    strcasecmp(options.identity_files[i], "none") == 0) {

- +		    strcasecmp(name, "none") == 0) {

-  			free(options.identity_files[i]);

-  			options.identity_files[i] = NULL;

-  			continue;

-  		}

- -		cp = tilde_expand_filename(options.identity_files[i], getuid());

- +#ifdef ENABLE_PKCS11

- +		if (strlen(name) >= strlen(PKCS11_URI_SCHEME) &&

- +		    strncmp(name, PKCS11_URI_SCHEME,

- +		    strlen(PKCS11_URI_SCHEME)) == 0) {

- +			load_pkcs11_identity(name, identity_files,

- +			    identity_keys, &n_ids);

- +			free(options.identity_files[i]);

- +			continue;

- +		}

- +#endif /* ENABLE_PKCS11 */

- +		cp = tilde_expand_filename(name, getuid());

-  		filename = percent_expand(cp, "d", pw->pw_dir,

-  		    "u", pw->pw_name, "l", thishost, "h", host,

-  		    "r", options.user, (char *)NULL);

- diff -up openssh/ssh-keygen.c.pkcs11-uri openssh/ssh-keygen.c

- --- openssh/ssh-keygen.c.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/ssh-keygen.c	2018-10-12 13:52:55.455191442 +0200

- @@ -825,6 +825,7 @@ do_download(struct passwd *pw)

-  			free(fp);

-  		} else {

-  			(void) sshkey_write(keys[i], stdout); /* XXX check */

- +			(void) pkcs11_uri_write(keys[i], stdout);

-  			fprintf(stdout, "\n");

-  		}

-  		sshkey_free(keys[i]);

- diff -up openssh/ssh-pkcs11-client.c.pkcs11-uri openssh/ssh-pkcs11-client.c

- --- openssh/ssh-pkcs11-client.c.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/ssh-pkcs11-client.c	2018-10-12 13:52:55.455191442 +0200

- @@ -126,6 +126,7 @@ pkcs11_rsa_private_encrypt(int flen, con

-  		return (-1);

-  	key.type = KEY_RSA;

-  	key.rsa = rsa;

- +	key.ecdsa_nid = 0;

-  	if ((r = sshkey_to_blob(&key, &blob, &blen)) != 0) {

-  		error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));

-  		return -1;

- @@ -210,6 +211,8 @@ pkcs11_add_provider(char *name, char *pi

-  	u_int nkeys, i;

-  	struct sshbuf *msg;

-  

- +	debug("%s: called, name = %s", __func__, name);

- +

-  	if (fd < 0 && pkcs11_start_helper() < 0)

-  		return (-1);

-  

- @@ -226,6 +229,7 @@ pkcs11_add_provider(char *name, char *pi

-  		if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)

-  			fatal("%s: buffer error: %s", __func__, ssh_err(r));

-  		*keysp = xcalloc(nkeys, sizeof(struct sshkey *));

- +		debug("%s: nkeys = %u", __func__, nkeys);

-  		for (i = 0; i < nkeys; i++) {

-  			/* XXX clean up properly instead of fatal() */

-  			if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||

- diff -up openssh/ssh-pkcs11.c.pkcs11-uri openssh/ssh-pkcs11.c

- --- openssh/ssh-pkcs11.c.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/ssh-pkcs11.c	2018-10-12 13:54:35.755023297 +0200

- @@ -49,8 +49,8 @@ struct pkcs11_slotinfo {

-  	int			logged_in;

-  };

-  

- -struct pkcs11_provider {

- -	char			*name;

- +struct pkcs11_module {

- +	char			*module_path;

-  	void			*handle;

-  	CK_FUNCTION_LIST	*function_list;

-  	CK_INFO			info;

- @@ -59,6 +59,13 @@ struct pkcs11_provider {

-  	struct pkcs11_slotinfo	*slotinfo;

-  	int			valid;

-  	int			refcount;

- +};

- +

- +struct pkcs11_provider {

- +	char			*name;

- +	struct pkcs11_module	*module; /* can be shared between various providers */

- +	int			refcount;

- +	int			valid;

-  	TAILQ_ENTRY(pkcs11_provider) next;

-  };

-  

- @@ -71,10 +78,46 @@ struct pkcs11_key {

-  	RSA_METHOD		*rsa_method;

-  	char			*keyid;

-  	int			keyid_len;

- +	char			*label;

-  };

-  

-  int pkcs11_interactive = 0;

-  

- +/*

- + * This can't be in the ssh-pkcs11-uri, becase we can not depend on

- + * PKCS#11 structures in ssh-agent (using client-helper communication)

- + */

- +int

- +pkcs11_uri_write(const struct sshkey *key, FILE *f)

- +{

- +	char *p = NULL;

- +	struct pkcs11_uri uri;

- +	struct pkcs11_key *k11;

- +

- +	/* sanity - is it a RSA key with associated app_data? */

- +	if (key->type != KEY_RSA ||

- +	    (k11 = RSA_get_app_data(key->rsa)) == NULL)

- +		return -1;

- +

- +	/* omit type -- we are looking for private-public or private-certificate pairs */

- +	uri.id = k11->keyid;

- +	uri.id_len = k11->keyid_len;

- +	uri.token = k11->provider->module->slotinfo[k11->slotidx].token.label;

- +	uri.object = k11->label;

- +	uri.module_path = k11->provider->module->module_path;

- +	uri.lib_manuf = k11->provider->module->info.manufacturerID;

- +	uri.manuf = k11->provider->module->slotinfo[k11->slotidx].token.manufacturerID;

- +

- +	p = pkcs11_uri_get(&uri);

- +	/* do not cleanup -- we do not allocate here, only reference */

- +	if (p == NULL)

- +		return -1;

- +

- +	fprintf(f, " %s", p);

- +	free(p);

- +	return 0;

- +}

- +

-  int

-  pkcs11_init(int interactive)

-  {

- @@ -90,26 +133,63 @@ pkcs11_init(int interactive)

-   * this is called when a provider gets unregistered.

-   */

-  static void

- -pkcs11_provider_finalize(struct pkcs11_provider *p)

- +pkcs11_module_finalize(struct pkcs11_module *m)

-  {

-  	CK_RV rv;

-  	CK_ULONG i;

-  

- -	debug("pkcs11_provider_finalize: %p refcount %d valid %d",

- -	    p, p->refcount, p->valid);

- -	if (!p->valid)

- +	debug("%s: %p refcount %d valid %d", __func__,

- +	    m, m->refcount, m->valid);

- +	if (!m->valid)

-  		return;

- -	for (i = 0; i < p->nslots; i++) {

- -		if (p->slotinfo[i].session &&

- -		    (rv = p->function_list->C_CloseSession(

- -		    p->slotinfo[i].session)) != CKR_OK)

- +	for (i = 0; i < m->nslots; i++) {

- +		if (m->slotinfo[i].session &&

- +		    (rv = m->function_list->C_CloseSession(

- +		    m->slotinfo[i].session)) != CKR_OK)

-  			error("C_CloseSession failed: %lu", rv);

-  	}

- -	if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK)

- +	if ((rv = m->function_list->C_Finalize(NULL)) != CKR_OK)

-  		error("C_Finalize failed: %lu", rv);

- +	m->valid = 0;

- +	m->function_list = NULL;

- +	dlclose(m->handle);

- +}

- +

- +/*

- + * remove a reference to the pkcs11 module.

- + * called when a provider is unregistered.

- + */

- +static void

- +pkcs11_module_unref(struct pkcs11_module *m)

- +{

- +	debug("%s: %p refcount %d", __func__, m, m->refcount);

- +	if (--m->refcount <= 0) {

- +		pkcs11_module_finalize(m);

- +		if (m->valid)

- +			error("%s: %p still valid", __func__, m);

- +		free(m->slotlist);

- +		free(m->slotinfo);

- +		free(m->module_path);

- +		free(m);

- +	}

- +}

- +

- +/*

- + * finalize a provider shared libarary, it's no longer usable.

- + * however, there might still be keys referencing this provider,

- + * so the actuall freeing of memory is handled by pkcs11_provider_unref().

- + * this is called when a provider gets unregistered.

- + */

- +static void

- +pkcs11_provider_finalize(struct pkcs11_provider *p)

- +{

- +	debug("%s: %p refcount %d valid %d", __func__,

- +	    p, p->refcount, p->valid);

- +	if (!p->valid)

- +		return;

- +	pkcs11_module_unref(p->module);

- +	p->module = NULL;

-  	p->valid = 0;

- -	p->function_list = NULL;

- -	dlclose(p->handle);

-  }

-  

-  /*

- @@ -119,12 +199,11 @@ pkcs11_provider_finalize(struct pkcs11_p

-  static void

-  pkcs11_provider_unref(struct pkcs11_provider *p)

-  {

- -	debug("pkcs11_provider_unref: %p refcount %d", p, p->refcount);

- +	debug("%s: %p refcount %d", __func__, p, p->refcount);

-  	if (--p->refcount <= 0) {

- -		if (p->valid)

- -			error("pkcs11_provider_unref: %p still valid", p);

- -		free(p->slotlist);

- -		free(p->slotinfo);

- +		if (p->module)

- +			pkcs11_module_unref(p->module);

- +		free(p->name);

-  		free(p);

-  	}

-  }

- @@ -142,6 +221,20 @@ pkcs11_terminate(void)

-  	}

-  }

-  

- +/* lookup provider by module path */

- +static struct pkcs11_module *

- +pkcs11_provider_lookup_module(char *module_path)

- +{

- +	struct pkcs11_provider *p;

- +

- +	TAILQ_FOREACH(p, &pkcs11_providers, next) {

- +		debug("check %p %s (%s)", p, p->name, p->module->module_path);

- +		if (!strcmp(module_path, p->module->module_path))

- +			return (p->module);

- +	}

- +	return (NULL);

- +}

- +

-  /* lookup provider by name */

-  static struct pkcs11_provider *

-  pkcs11_provider_lookup(char *provider_id)

- @@ -156,19 +249,52 @@ pkcs11_provider_lookup(char *provider_id

-  	return (NULL);

-  }

-  

- +int pkcs11_del_provider_by_uri(struct pkcs11_uri *);

- +

-  /* unregister provider by name */

-  int

-  pkcs11_del_provider(char *provider_id)

-  {

- +	int rv;

- +	struct pkcs11_uri *uri;

- +

- +	debug("%s: called, provider_id = %s", __func__, provider_id);

- +

- +	uri = pkcs11_uri_init();

- +	if (uri == NULL)

- +		fatal("Failed to init PCKS#11 URI");

- +

- +	if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) &&

- +	    strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) {

- +		if (pkcs11_uri_parse(provider_id, uri) != 0)

- +			fatal("Failed to parse PKCS#11 URI");

- +	} else {

- +		uri->module_path = strdup(provider_id);

- +	}

- +

- +	rv = pkcs11_del_provider_by_uri(uri);

- +	pkcs11_uri_cleanup(uri);

- +	return rv;

- +}

- +

- +/* unregister provider by PKCS#11 URI */

- +int

- +pkcs11_del_provider_by_uri(struct pkcs11_uri *uri)

- +{

-  	struct pkcs11_provider *p;

- +	int rv = -1;

- +	char *provider_uri = pkcs11_uri_get(uri);

-  

- -	if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {

- +	debug3("%s(%s): called", __func__, provider_uri);

- +

- +	if ((p = pkcs11_provider_lookup(provider_uri)) != NULL) {

-  		TAILQ_REMOVE(&pkcs11_providers, p, next);

-  		pkcs11_provider_finalize(p);

-  		pkcs11_provider_unref(p);

- -		return (0);

- +		rv = 0;

-  	}

- -	return (-1);

- +	free(provider_uri);

- +	return rv;

-  }

-  

-  /* openssl callback for freeing an RSA key */

- @@ -185,6 +311,7 @@ pkcs11_rsa_finish(RSA *rsa)

-  			pkcs11_provider_unref(k11->provider);

-  		RSA_meth_free(k11->rsa_method);

-  		free(k11->keyid);

- +		free(k11->label);

-  		free(k11);

-  	}

-  	return (rv);

- @@ -201,8 +328,8 @@ pkcs11_find(struct pkcs11_provider *p, C

-  	CK_RV			rv;

-  	int			ret = -1;

-  

- -	f = p->function_list;

- -	session = p->slotinfo[slotidx].session;

- +	f = p->module->function_list;

- +	session = p->module->slotinfo[slotidx].session;

-  	if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) {

-  		error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv);

-  		return (-1);

- @@ -249,12 +376,13 @@ pkcs11_rsa_private_encrypt(int flen, con

-  		error("RSA_get_app_data failed for rsa %p", rsa);

-  		return (-1);

-  	}

- -	if (!k11->provider || !k11->provider->valid) {

- +	if (!k11->provider || !k11->provider->valid || !k11->provider->module

- +	    || !k11->provider->module->valid) {

-  		error("no pkcs11 (valid) provider for rsa %p", rsa);

-  		return (-1);

-  	}

- -	f = k11->provider->function_list;

- -	si = &k11->provider->slotinfo[k11->slotidx];

- +	f = k11->provider->module->function_list;

- +	si = &k11->provider->module->slotinfo[k11->slotidx];

-  	if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {

-  		if (!pkcs11_interactive) {

-  			error("need pin entry%s", (si->token.flags &

- @@ -313,7 +441,7 @@ pkcs11_rsa_private_decrypt(int flen, con

-  /* redirect private key operations for rsa key to pkcs11 token */

-  static int

-  pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,

- -    CK_ATTRIBUTE *keyid_attrib, RSA *rsa)

- +    CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, RSA *rsa)

-  {

-  	struct pkcs11_key	*k11;

-  	const RSA_METHOD	*def = RSA_get_default_method();

- @@ -328,6 +456,11 @@ pkcs11_rsa_wrap(struct pkcs11_provider *

-  		k11->keyid = xmalloc(k11->keyid_len);

-  		memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);

-  	}

- +	if (label_attrib->ulValueLen > 0 ) {

- +		k11->label = xmalloc(label_attrib->ulValueLen+1);

- +		memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen);

- +		k11->label[label_attrib->ulValueLen] = 0;

- +	}

-  	k11->rsa_method = RSA_meth_dup(def);

-  	if (k11->rsa_method == NULL)

-  		fatal("%s: RSA_meth_dup failed", __func__);

- @@ -371,16 +504,16 @@ pkcs11_open_session(struct pkcs11_provid

-  	CK_SESSION_HANDLE	session;

-  	int			login_required;

-  

- -	f = p->function_list;

- -	login_required = p->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED;

- +	f = p->module->function_list;

- +	login_required = p->module->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED;

-  	if (pin && login_required && !strlen(pin)) {

-  		error("pin required");

-  		return (-1);

-  	}

- -	if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|

- +	if ((rv = f->C_OpenSession(p->module->slotlist[slotidx], CKF_RW_SESSION|

-  	    CKF_SERIAL_SESSION, NULL, NULL, &session))

-  	    != CKR_OK) {

- -		error("C_OpenSession failed: %lu", rv);

- +		error("C_OpenSession failed for slot %lu: %lu", slotidx, rv);

-  		return (-1);

-  	}

-  	if (login_required && pin) {

- @@ -392,9 +525,9 @@ pkcs11_open_session(struct pkcs11_provid

-  				error("C_CloseSession failed: %lu", rv);

-  			return (-1);

-  		}

- -		p->slotinfo[slotidx].logged_in = 1;

- +		p->module->slotinfo[slotidx].logged_in = 1;

-  	}

- -	p->slotinfo[slotidx].session = session;

- +	p->module->slotinfo[slotidx].session = session;

-  	return (0);

-  }

-  

- @@ -404,39 +537,72 @@ pkcs11_open_session(struct pkcs11_provid

-   * keysp points to an (possibly empty) array with *nkeys keys.

-   */

-  static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG,

- -    CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *)

- +    CK_ATTRIBUTE [], size_t, CK_ATTRIBUTE [3], struct sshkey ***, int *)

-  	__attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE))));

-  

-  static int

-  pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,

- -    struct sshkey ***keysp, int *nkeys)

- +    struct sshkey ***keysp, int *nkeys, struct pkcs11_uri *uri)

-  {

- +	size_t filter_size = 1;

-  	CK_OBJECT_CLASS	pubkey_class = CKO_PUBLIC_KEY;

-  	CK_OBJECT_CLASS	cert_class = CKO_CERTIFICATE;

-  	CK_ATTRIBUTE		pubkey_filter[] = {

- -		{ CKA_CLASS, NULL, sizeof(pubkey_class) }

- +		{ CKA_CLASS, NULL, sizeof(pubkey_class) },

- +		{ CKA_ID, NULL, 0 },

- +		{ CKA_LABEL, NULL, 0 }

-  	};

-  	CK_ATTRIBUTE		cert_filter[] = {

- -		{ CKA_CLASS, NULL, sizeof(cert_class) }

- +		{ CKA_CLASS, NULL, sizeof(cert_class) },

- +		{ CKA_ID, NULL, 0 },

- +		{ CKA_LABEL, NULL, 0 }

-  	};

-  	CK_ATTRIBUTE		pubkey_attribs[] = {

-  		{ CKA_ID, NULL, 0 },

- +		{ CKA_LABEL, NULL, 0 },

-  		{ CKA_MODULUS, NULL, 0 },

-  		{ CKA_PUBLIC_EXPONENT, NULL, 0 }

-  	};

-  	CK_ATTRIBUTE		cert_attribs[] = {

-  		{ CKA_ID, NULL, 0 },

- +		{ CKA_LABEL, NULL, 0 },

-  		{ CKA_SUBJECT, NULL, 0 },

-  		{ CKA_VALUE, NULL, 0 }

-  	};

-  	pubkey_filter[0].pValue = &pubkey_class;

-  	cert_filter[0].pValue = &cert_class;

-  

- -	if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs,

- -	    keysp, nkeys) < 0 ||

- -	    pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs,

- -	    keysp, nkeys) < 0)

- +	if (uri->id != NULL) {

- +		pubkey_filter[filter_size].pValue = uri->id;

- +		pubkey_filter[filter_size].ulValueLen = uri->id_len;

- +		cert_filter[filter_size].pValue = uri->id;

- +		cert_filter[filter_size].ulValueLen = uri->id_len;

- +		filter_size++;

- +	}

- +	if (uri->object != NULL) {

- +		pubkey_filter[filter_size].pValue = uri->object;

- +		pubkey_filter[filter_size].ulValueLen = strlen(uri->object);

- +		pubkey_filter[filter_size].type = CKA_LABEL;

- +		cert_filter[filter_size].pValue = uri->object;

- +		cert_filter[filter_size].ulValueLen = strlen(uri->object);

- +		cert_filter[filter_size].type = CKA_LABEL;

- +		filter_size++;

- +	}

- +

- +	if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, filter_size,

- +	    pubkey_attribs, keysp, nkeys) < 0 ||

- +	    pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size,

- +	    cert_attribs, keysp, nkeys) < 0)

-  		return (-1);

- +	if (*nkeys == 0) {

- +		/* Try once more without the label filter */

- +		filter_size--;

- +		if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, filter_size,

- +		    pubkey_attribs, keysp, nkeys) < 0 ||

- +		    pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size,

- +		    cert_attribs, keysp, nkeys) < 0)

- +	 		return (-1);

- +	}

-  	return (0);

-  }

-  

- @@ -462,14 +619,15 @@ have_rsa_key(const RSA *rsa)

-  

-  static int

-  pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,

- -    CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3],

- +    CK_ATTRIBUTE filter[], size_t filter_size, CK_ATTRIBUTE attribs[4],

-      struct sshkey ***keysp, int *nkeys)

-  {

-  	struct sshkey		*key;

-  	RSA			*rsa;

-  	X509 			*x509;

- -	EVP_PKEY		*evp;

- +	EVP_PKEY		*evp = NULL;

-  	int			i;

- +	int			nattribs = 4;

-  	const u_char		*cp;

-  	CK_RV			rv;

-  	CK_OBJECT_HANDLE	obj;

- @@ -477,16 +635,15 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  	CK_SESSION_HANDLE	session;

-  	CK_FUNCTION_LIST	*f;

-  

- -	f = p->function_list;

- -	session = p->slotinfo[slotidx].session;

- +	f = p->module->function_list;

- +	session = p->module->slotinfo[slotidx].session;

-  	/* setup a filter the looks for public keys */

- -	if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) {

- +	if ((rv = f->C_FindObjectsInit(session, filter, filter_size)) != CKR_OK) {

-  		error("C_FindObjectsInit failed: %lu", rv);

-  		return (-1);

-  	}

-  	while (1) {

- -		/* XXX 3 attributes in attribs[] */

- -		for (i = 0; i < 3; i++) {

- +		for (i = 0; i < nattribs; i++) {

-  			attribs[i].pValue = NULL;

-  			attribs[i].ulValueLen = 0;

-  		}

- @@ -494,22 +651,22 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  		    || nfound == 0)

-  			break;

-  		/* found a key, so figure out size of the attributes */

- -		if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))

- +		if ((rv = f->C_GetAttributeValue(session, obj, attribs, nattribs))

-  		    != CKR_OK) {

-  			error("C_GetAttributeValue failed: %lu", rv);

-  			continue;

-  		}

-  		/*

- -		 * Allow CKA_ID (always first attribute) to be empty, but

- -		 * ensure that none of the others are zero length.

- +		 * Allow CKA_ID (always first attribute) and CKA_LABEL (second)

- +		 * to be empty, but ensure that none of the others are zero length.

-  		 * XXX assumes CKA_ID is always first.

-  		 */

- -		if (attribs[1].ulValueLen == 0 ||

- -		    attribs[2].ulValueLen == 0) {

- +		if (attribs[2].ulValueLen == 0 ||

- +		    attribs[3].ulValueLen == 0) {

-  			continue;

-  		}

-  		/* allocate buffers for attributes */

- -		for (i = 0; i < 3; i++) {

- +		for (i = 0; i < nattribs; i++) {

-  			if (attribs[i].ulValueLen > 0) {

-  				attribs[i].pValue = xmalloc(

-  				    attribs[i].ulValueLen);

- @@ -517,23 +674,23 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  		}

-  

-  		/*

- -		 * retrieve ID, modulus and public exponent of RSA key,

- -		 * or ID, subject and value for certificates.

- +		 * retrieve ID, label, modulus and public exponent of RSA key,

- +		 * or ID, label, subject and value for certificates.

-  		 */

-  		rsa = NULL;

- -		if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))

- +		if ((rv = f->C_GetAttributeValue(session, obj, attribs, nattribs))

-  		    != CKR_OK) {

-  			error("C_GetAttributeValue failed: %lu", rv);

- -		} else if (attribs[1].type == CKA_MODULUS ) {

- +		} else if (attribs[2].type == CKA_MODULUS ) {

-  			if ((rsa = RSA_new()) == NULL) {

-  				error("RSA_new failed");

-  			} else {

-  				BIGNUM *rsa_n, *rsa_e;

-  

- -				rsa_n = BN_bin2bn(attribs[1].pValue,

- -				    attribs[1].ulValueLen, NULL);

- -				rsa_e = BN_bin2bn(attribs[2].pValue,

- +				rsa_n = BN_bin2bn(attribs[2].pValue,

-  				    attribs[2].ulValueLen, NULL);

- +				rsa_e = BN_bin2bn(attribs[3].pValue,

- +				    attribs[3].ulValueLen, NULL);

-  				if (rsa_n != NULL && rsa_e != NULL) {

-  					if (!RSA_set0_key(rsa,

-  					    rsa_n, rsa_e, NULL))

- @@ -544,10 +701,10 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  				BN_free(rsa_e);

-  			}

-  		} else {

- -			cp = attribs[2].pValue;

- +			cp = attribs[3].pValue;

-  			if ((x509 = X509_new()) == NULL) {

-  				error("X509_new failed");

- -			} else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen)

- +			} else if (d2i_X509(&x509, &cp, attribs[3].ulValueLen)

-  			    == NULL) {

-  				error("d2i_X509 failed");

-  			} else if ((evp = X509_get_pubkey(x509)) == NULL ||

- @@ -559,9 +716,10 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  				error("RSAPublicKey_dup");

-  			}

-  			X509_free(x509);

- +			EVP_PKEY_free(evp);

-  		}

-  		if (rsa && have_rsa_key(rsa) &&

- -		    pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {

- +		    pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) {

-  			if ((key = sshkey_new(KEY_UNSPEC)) == NULL)

-  				fatal("sshkey_new failed");

-  			key->rsa = rsa;

- @@ -580,7 +738,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  		} else if (rsa) {

-  			RSA_free(rsa);

-  		}

- -		for (i = 0; i < 3; i++)

- +		for (i = 0; i < nattribs; i++)

-  			free(attribs[i].pValue);

-  	}

-  	if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)

- @@ -592,126 +750,240 @@ pkcs11_fetch_keys_filter(struct pkcs11_p

-  int

-  pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)

-  {

- -	int nkeys, need_finalize = 0;

- -	struct pkcs11_provider *p = NULL;

- +	int rv;

- +	struct pkcs11_uri *uri;

- +

- +	debug("%s: called, provider_id = %s", __func__, provider_id);

- +

- +	uri = pkcs11_uri_init();

- +	if (uri == NULL)

- +		fatal("Failed to init PCKS#11 URI");

- +

- +	if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) &&

- +	    strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) {

- +		if (pkcs11_uri_parse(provider_id, uri) != 0)

- +			fatal("Failed to parse PKCS#11 URI");

- +	} else {

- +		uri->module_path = strdup(provider_id);

- +	}

- +

- +	rv = pkcs11_add_provider_by_uri(uri, pin, keyp);

- +	pkcs11_uri_cleanup(uri);

- +	return rv;

- +}

- +

- +struct pkcs11_provider *

- +pkcs11_provider_initialize(struct pkcs11_uri *uri)

- +{

- +	int need_finalize = 0;

-  	void *handle = NULL;

-  	CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);

-  	CK_RV rv;

-  	CK_FUNCTION_LIST *f = NULL;

-  	CK_TOKEN_INFO *token;

-  	CK_ULONG i;

- +	char *provider_module = NULL;

- +	struct pkcs11_provider *p;

- +	struct pkcs11_module *m;

-  

- -	*keyp = NULL;

- -	if (pkcs11_provider_lookup(provider_id) != NULL) {

- -		debug("%s: provider already registered: %s",

- -		    __func__, provider_id);

- +	/* if no provider specified, fallback to p11-kit */

- +	if (uri->module_path == NULL) {

- +#ifdef PKCS11_DEFAULT_PROVIDER

- +		provider_module = strdup(PKCS11_DEFAULT_PROVIDER);

- +#else

- +		error("%s: No module path provided", __func__);

-  		goto fail;

- +#endif

- +	} else

- +		provider_module = strdup(uri->module_path);

- +

- +	p = xcalloc(1, sizeof(*p));

- +	p->name = pkcs11_uri_get(uri);

- +

- +	if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL

- +	    && m->valid) {

- +		debug("%s: provider module already initialized: %s",

- +		    __func__, provider_module);

- +		free(provider_module);

- +		/* Skip the initialization of PKCS#11 module */

- +		m->refcount++;

- +		p->module = m;

- +		p->valid = 1;

- +		TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);

- +		p->refcount++;	/* add to provider list */

- +		return p;

- +	} else {

- +		m = xcalloc(1, sizeof(*m));

- +		p->module = m;

- +		m->refcount++;

-  	}

- +

-  	/* open shared pkcs11-libarary */

- -	if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {

- -		error("dlopen %s failed: %s", provider_id, dlerror());

- +	if ((handle = dlopen(provider_module, RTLD_NOW)) == NULL) {

- +		error("dlopen %s failed: %s", provider_module, dlerror());

-  		goto fail;

-  	}

-  	if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) {

-  		error("dlsym(C_GetFunctionList) failed: %s", dlerror());

-  		goto fail;

-  	}

- -	p = xcalloc(1, sizeof(*p));

- -	p->name = xstrdup(provider_id);

- -	p->handle = handle;

- +	m->handle = handle;

-  	/* setup the pkcs11 callbacks */

-  	if ((rv = (*getfunctionlist)(&f)) != CKR_OK) {

-  		error("C_GetFunctionList for provider %s failed: %lu",

- -		    provider_id, rv);

- +		    provider_module, rv);

-  		goto fail;

-  	}

- -	p->function_list = f;

- +	m->function_list = f;

-  	if ((rv = f->C_Initialize(NULL)) != CKR_OK) {

-  		error("C_Initialize for provider %s failed: %lu",

- -		    provider_id, rv);

- +		    provider_module, rv);

-  		goto fail;

-  	}

-  	need_finalize = 1;

- -	if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) {

- +	if ((rv = f->C_GetInfo(&m->info)) != CKR_OK) {

-  		error("C_GetInfo for provider %s failed: %lu",

- -		    provider_id, rv);

- +		    provider_module, rv);

- +		goto fail;

- +	}

- +	rmspace(m->info.manufacturerID, sizeof(m->info.manufacturerID));

- +	if (uri->lib_manuf != NULL &&

- +	    strcmp(uri->lib_manuf, m->info.manufacturerID)) {

- +		debug("%s: Skipping provider %s not matching library_manufacturer",

- +		    __func__, m->info.manufacturerID);

-  		goto fail;

-  	}

- -	rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID));

- -	rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription));

- +	rmspace(m->info.libraryDescription, sizeof(m->info.libraryDescription));

-  	debug("provider %s: manufacturerID <%s> cryptokiVersion %d.%d"

-  	    " libraryDescription <%s> libraryVersion %d.%d",

- -	    provider_id,

- -	    p->info.manufacturerID,

- -	    p->info.cryptokiVersion.major,

- -	    p->info.cryptokiVersion.minor,

- -	    p->info.libraryDescription,

- -	    p->info.libraryVersion.major,

- -	    p->info.libraryVersion.minor);

- -	if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) {

- +	    provider_module,

- +	    m->info.manufacturerID,

- +	    m->info.cryptokiVersion.major,

- +	    m->info.cryptokiVersion.minor,

- +	    m->info.libraryDescription,

- +	    m->info.libraryVersion.major,

- +	    m->info.libraryVersion.minor);

- +

- +	if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &m->nslots)) != CKR_OK) {

-  		error("C_GetSlotList failed: %lu", rv);

-  		goto fail;

-  	}

- -	if (p->nslots == 0) {

- +	if (m->nslots == 0) {

-  		debug("%s: provider %s returned no slots", __func__,

- -		    provider_id);

- +		    provider_module);

-  		goto fail;

-  	}

- -	p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));

- -	if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))

- +	m->slotlist = xcalloc(m->nslots, sizeof(CK_SLOT_ID));

- +	if ((rv = f->C_GetSlotList(CK_TRUE, m->slotlist, &m->nslots))

-  	    != CKR_OK) {

-  		error("C_GetSlotList for provider %s failed: %lu",

- -		    provider_id, rv);

- +		    provider_module, rv);

-  		goto fail;

-  	}

- -	p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));

- +	m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo));

- +	m->valid = 1;

-  	p->valid = 1;

- -	nkeys = 0;

- -	for (i = 0; i < p->nslots; i++) {

- -		token = &p->slotinfo[i].token;

- -		if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))

- +

- +	for (i = 0; i < m->nslots; i++) {

- +		token = &m->slotinfo[i].token;

- +		if ((rv = f->C_GetTokenInfo(m->slotlist[i], token))

-  		    != CKR_OK) {

-  			error("C_GetTokenInfo for provider %s slot %lu "

- -			    "failed: %lu", provider_id, (unsigned long)i, rv);

- +			    "failed: %lu", provider_module, (unsigned long)i, rv);

-  			continue;

-  		}

-  		if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {

- -			debug2("%s: ignoring uninitialised token in "

- -			    "provider %s slot %lu", __func__,

- -			    provider_id, (unsigned long)i);

-  			continue;

-  		}

-  		rmspace(token->label, sizeof(token->label));

-  		rmspace(token->manufacturerID, sizeof(token->manufacturerID));

-  		rmspace(token->model, sizeof(token->model));

-  		rmspace(token->serialNumber, sizeof(token->serialNumber));

- +	}

- +	m->module_path = provider_module;

- +	provider_module = NULL;

- +

- +	/* insert unconditionally -- remove if there will be no keys later */

- +	TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);

- +	p->refcount++;	/* add to provider list */

- +	return p;

- +

- +fail:

- +	if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)

- +		error("C_Finalize for provider %s failed: %lu",

- +		    provider_module, rv);

- +	free(provider_module);

- +	free(p);

- +	if (handle)

- +		dlclose(handle);

- +	return NULL;

- +}

- +

- +int

- +pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin, struct sshkey ***keyp)

- +{

- +	int nkeys;

- +	struct pkcs11_provider *p = NULL;

- +	CK_TOKEN_INFO *token;

- +	CK_ULONG i;

- +	char *provider_uri = pkcs11_uri_get(uri);

- +

- +	debug("%s: called, provider_uri = %s", __func__, provider_uri);

- +

- +	*keyp = NULL;

- +	if ((p = pkcs11_provider_initialize(uri)) == NULL) {

- +		debug("%s: failed to initialize provider: %s",

- +		    __func__, provider_uri);

- +		goto fail;

- +	}

- +

- +	nkeys = 0;

- +	for (i = 0; i < p->module->nslots; i++) {

- +		token = &p->module->slotinfo[i].token;

- +		if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {

- +			debug2("%s: ignoring uninitialised token in "

- +			    "provider %s slot %lu", __func__,

- +			    provider_uri, (unsigned long)i);

- +			continue;

- +		}

- +		if (uri->token != NULL &&

- +		    strcmp(token->label, uri->token) != 0) {

- +			debug2("%s: ignoring token not matching label (%s) "

- +			    "specified by PKCS#11 URI in slot %lu", __func__,

- +			    token->label, (unsigned long)i);

- +			continue;

- +		}

- +		if (uri->manuf != NULL &&

- +		    strcmp(token->manufacturerID, uri->manuf) != 0) {

- +			debug2("%s: ignoring token not matching requrested "

- +			    "manufacturerID (%s) specified by PKCS#11 URI in "

- +			    "slot %lu", __func__,

- +			    token->manufacturerID, (unsigned long)i);

- +			continue;

- +		}

-  		debug("provider %s slot %lu: label <%s> manufacturerID <%s> "

-  		    "model <%s> serial <%s> flags 0x%lx",

- -		    provider_id, (unsigned long)i,

- +		    provider_uri, (unsigned long)i,

-  		    token->label, token->manufacturerID, token->model,

-  		    token->serialNumber, token->flags);

- -		/* open session, login with pin and retrieve public keys */

- -		if (pkcs11_open_session(p, i, pin) == 0)

- -			pkcs11_fetch_keys(p, i, keyp, &nkeys);

- +		/* open session if not yet opened, login with pin

- +		 * and retrieve public keys */

- +		if ((p->module->slotinfo[i].session != 0) ||

- +		    pkcs11_open_session(p, i, pin) == 0)

- +			pkcs11_fetch_keys(p, i, keyp, &nkeys, uri);

-  	}

-  	if (nkeys > 0) {

- -		TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);

- -		p->refcount++;	/* add to provider list */

- +		free(provider_uri);

-  		return (nkeys);

-  	}

- -	debug("%s: provider %s returned no keys", __func__, provider_id);

- +	debug("%s: provider %s returned no keys", __func__, provider_uri);

-  	/* don't add the provider, since it does not have any keys */

-  fail:

- -	if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)

- -		error("C_Finalize for provider %s failed: %lu",

- -		    provider_id, rv);

-  	if (p) {

- -		free(p->slotlist);

- -		free(p->slotinfo);

- -		free(p);

- + 		TAILQ_REMOVE(&pkcs11_providers, p, next);

- +		pkcs11_provider_unref(p);

-  	}

- -	if (handle)

- -		dlclose(handle);

- +	free(provider_uri);

-  	return (-1);

-  }

-  

- diff -up openssh/ssh-pkcs11.h.pkcs11-uri openssh/ssh-pkcs11.h

- --- openssh/ssh-pkcs11.h.pkcs11-uri	2018-10-11 02:56:36.000000000 +0200

- +++ openssh/ssh-pkcs11.h	2018-10-12 13:52:55.457191459 +0200

- @@ -14,10 +14,15 @@

-   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF

-   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

-   */

- +

- +#include "ssh-pkcs11-uri.h"

- +

-  int	pkcs11_init(int);

-  void	pkcs11_terminate(void);

-  int	pkcs11_add_provider(char *, char *, struct sshkey ***);

- +int	pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***);

-  int	pkcs11_del_provider(char *);

- +int	pkcs11_uri_write(const struct sshkey *, FILE *);

-  

-  #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11)

-  #undef ENABLE_PKCS11

- diff -up openssh/ssh-pkcs11-uri.c.pkcs11-uri openssh/ssh-pkcs11-uri.c

- --- openssh/ssh-pkcs11-uri.c.pkcs11-uri	2018-10-12 13:52:55.456191450 +0200

- +++ openssh/ssh-pkcs11-uri.c	2018-10-12 13:52:55.455191442 +0200

- @@ -0,0 +1,395 @@

- +/*

- + * Copyright (c) 2017 Red Hat

- + *

- + * Authors: Jakub Jelen <jjelen@redhat.com>

- + *

- + * Permission to use, copy, modify, and distribute this software for any

- + * purpose with or without fee is hereby granted, provided that the above

- + * copyright notice and this permission notice appear in all copies.

- + *

- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES

- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF

- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR

- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES

- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN

- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF

- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

- + */

- +

- +#include "includes.h"

- +

- +#ifdef ENABLE_PKCS11

- +

- +#include <stdio.h>

- +#include <string.h>

- +

- +#include "sshkey.h"

- +#include "sshbuf.h"

- +#include "log.h"

- +

- +#define CRYPTOKI_COMPAT

- +#include "pkcs11.h"

- +

- +#include "ssh-pkcs11-uri.h"

- +

- +#define PKCS11_URI_PATH_SEPARATOR ";"

- +#define PKCS11_URI_QUERY_SEPARATOR "&"

- +#define PKCS11_URI_VALUE_SEPARATOR "="

- +#define PKCS11_URI_ID "id"

- +#define PKCS11_URI_TOKEN "token"

- +#define PKCS11_URI_OBJECT "object"

- +#define PKCS11_URI_LIB_MANUF "library-manufacturer"

- +#define PKCS11_URI_MANUF "manufacturer"

- +#define PKCS11_URI_MODULE_PATH "module-path"

- +

- +/* Keyword tokens. */

- +typedef enum {

- +	pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pModulePath,

- +	pBadOption

- +} pkcs11uriOpCodes;

- +

- +/* Textual representation of the tokens. */

- +static struct {

- +	const char *name;

- +	pkcs11uriOpCodes opcode;

- +} keywords[] = {

- +	{ PKCS11_URI_ID, pId },

- +	{ PKCS11_URI_TOKEN, pToken },

- +	{ PKCS11_URI_OBJECT, pObject },

- +	{ PKCS11_URI_LIB_MANUF, pLibraryManufacturer },

- +	{ PKCS11_URI_MANUF, pManufacturer },

- +	{ PKCS11_URI_MODULE_PATH, pModulePath },

- +	{ NULL, pBadOption }

- +};

- +

- +static pkcs11uriOpCodes

- +parse_token(const char *cp)

- +{

- +	u_int i;

- +

- +	for (i = 0; keywords[i].name; i++)

- +		if (strncasecmp(cp, keywords[i].name,

- +		    strlen(keywords[i].name)) == 0)

- +			return keywords[i].opcode;

- +

- +	return pBadOption;

- +}

- +

- +int

- +percent_decode(char *data, char **outp)

- +{

- +	char tmp[3];

- +	char *out, *tmp_end;

- +	char *p = data;

- +	long value;

- +	size_t outlen = 0;

- +

- +	out = malloc(strlen(data)+1); /* upper bound */

- +	if (out == NULL)

- +		return -1;

- +	while (*p != '\0') {

- +		switch (*p) {

- +		case '%':

- +			p++;

- +			if (*p == '\0')

- +				goto fail;

- +			tmp[0] = *p++;

- +			if (*p == '\0')

- +				goto fail;

- +			tmp[1] = *p++;

- +			tmp[2] = '\0';

- +			tmp_end = NULL;

- +			value = strtol(tmp, &tmp_end, 16);

- +			if (tmp_end != tmp+2)

- +				goto fail;

- +			else

- +				out[outlen++] = (char) value;

- +			break;

- +		default:

- +			out[outlen++] = *p++;

- +			break;

- +		}

- +	}

- +

- +	/* zero terminate */

- +	out[outlen] = '\0';

- +	*outp = out;

- +	return outlen;

- +fail:

- +	free(out);

- +	return -1;

- +}

- +

- +struct sshbuf *

- +percent_encode(const char *data, size_t length, const char *whitelist)

- +{

- +	struct sshbuf *b = NULL;

- +	char tmp[4], *cp;

- +	size_t i;

- +

- +	if ((b = sshbuf_new()) == NULL)

- +		return NULL;

- +	for (i = 0; i < length; i++) {

- +		cp = strchr(whitelist, data[i]);

- +		/* if c is specified as '\0' pointer to terminator is returned !! */

- +		if (cp != NULL && *cp != '\0') {

- +			if (sshbuf_put(b, &data[i], 1) != 0)

- +				goto err;

- +		} else

- +			if (snprintf(tmp, 4, "%%%02X", (unsigned char) data[i]) < 3

- +			    || sshbuf_put(b, tmp, 3) != 0)

- +				goto err;

- +	}

- +	if (sshbuf_put(b, "\0", 1) == 0)

- +		return b;

- +err:

- +	sshbuf_free(b);

- +	return NULL;

- +}

- +

- +char *

- +pkcs11_uri_append(char *part, const char *separator, const char *key,

- +    struct sshbuf *value)

- +{

- +	char *new_part;

- +	size_t size = 0;

- +

- +	if (value == NULL)

- +		return NULL;

- +

- +	size = asprintf(&new_part,

- +	    "%s%s%s"  PKCS11_URI_VALUE_SEPARATOR "%s",

- +	    (part != NULL ? part : ""),

- +	    (part != NULL ? separator : ""),

- +	    key, sshbuf_ptr(value));

- +	sshbuf_free(value);

- +	free(part);

- +

- +	if (size <= 0)

- +		return NULL;

- +	return new_part;

- +}

- +

- +char *

- +pkcs11_uri_get(struct pkcs11_uri *uri)

- +{

- +	size_t size = 0;

- +	char *p = NULL, *path = NULL, *query = NULL;

- +

- +	/* compose a percent-encoded ID */

- +	if (uri->id_len > 0) {

- +		struct sshbuf *key_id = percent_encode(uri->id, uri->id_len, "");

- +		path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,

- +		    PKCS11_URI_ID, key_id);

- +		if (path == NULL)

- +			goto err;

- +	}

- +

- +	/* Write object label */

- +	if (uri->object) {

- +		struct sshbuf *label = percent_encode(uri->object, strlen(uri->object),

- +		    PKCS11_URI_WHITELIST);

- +		path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,

- +		    PKCS11_URI_OBJECT, label);

- +		if (path == NULL)

- +			goto err;

- +	}

- +

- +	/* Write token label */

- +	if (uri->token) {

- +		struct sshbuf *label = percent_encode(uri->token, strlen(uri->token),

- +		    PKCS11_URI_WHITELIST);

- +		path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,

- +		    PKCS11_URI_TOKEN, label);

- +		if (path == NULL)

- +			goto err;

- +	}

- +

- +	/* Write manufacturer */

- +	if (uri->manuf) {

- +		struct sshbuf *manuf = percent_encode(uri->manuf,

- +		    strlen(uri->manuf), PKCS11_URI_WHITELIST);

- +		path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,

- +		    PKCS11_URI_MANUF, manuf);

- +		if (path == NULL)

- +			goto err;

- +	}

- +

- +	/* Write module_path */

- +	if (uri->module_path) {

- +		struct sshbuf *module = percent_encode(uri->module_path,

- +		    strlen(uri->module_path), PKCS11_URI_WHITELIST "/");

- +		query = pkcs11_uri_append(query, PKCS11_URI_QUERY_SEPARATOR,

- +		    PKCS11_URI_MODULE_PATH, module);

- +		if (query == NULL)

- +			goto err;

- +	}

- +

- +	size = asprintf(&p, PKCS11_URI_SCHEME "%s%s%s",

- +	    path != NULL ? path : "",

- +	    query != NULL ? "?" : "",

- +	    query != NULL ? query : "");

- +err:

- +	free(query);

- +	free(path);

- +	if (size <= 0)

- +		return NULL;

- +	return p;

- +}

- +

- +struct pkcs11_uri *

- +pkcs11_uri_init()

- +{

- +	struct pkcs11_uri *d = calloc(1, sizeof(struct pkcs11_uri));

- +	return d;

- +}

- +

- +void

- +pkcs11_uri_cleanup(struct pkcs11_uri *pkcs11)

- +{

- +	free(pkcs11->id);

- +	free(pkcs11->module_path);

- +	free(pkcs11->token);

- +	free(pkcs11->object);

- +	free(pkcs11->lib_manuf);

- +	free(pkcs11->manuf);

- +	free(pkcs11);

- +}

- +

- +int

- +pkcs11_uri_parse(const char *uri, struct pkcs11_uri *pkcs11)

- +{

- +	char *saveptr1, *saveptr2, *str1, *str2, *tok;

- +	int rv = 0, len;

- +	char *p = NULL;

- +

- +	size_t scheme_len = strlen(PKCS11_URI_SCHEME);

- +	if (strlen(uri) < scheme_len || /* empty URI matches everything */

- +	    strncmp(uri, PKCS11_URI_SCHEME, scheme_len) != 0) {

- +		error("%s: The '%s' does not look like PKCS#11 URI",

- +		    __func__, uri);

- +		return -1;

- +	}

- +

- +	if (pkcs11 == NULL) {

- +		error("%s: Bad arguments. The pkcs11 can't be null", __func__);

- +		return -1;

- +	}

- +

- +	/* skip URI schema name */

- +	p = strdup(uri);

- +	str1 = p;

- +

- +	/* everything before ? */

- +	tok = strtok_r(str1, "?", &saveptr1);

- +	if (tok == NULL) {

- +		free(p);

- +		error("%s: pk11-path expected, got EOF", __func__);

- +		return -1;

- +	}

- +

- +	/* skip URI schema name:

- +	 * the scheme ensures that there is at least something before "?"

- +	 * allowing empty pk11-path. Resulting token at worst pointing to

- +	 * \0 byte */

- +	tok = tok + scheme_len;

- +

- +	/* parse pk11-path */

- +	for (str2 = tok; ; str2 = NULL) {

- +		char **charptr;

- +		pkcs11uriOpCodes opcode;

- +		tok = strtok_r(str2, PKCS11_URI_PATH_SEPARATOR, &saveptr2);

- +		if (tok == NULL)

- +			break;

- +		opcode = parse_token(tok);

- +

- +		char *arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */

- +		switch (opcode) {

- +		case pId:

- +			/* CKA_ID */

- +			if (pkcs11->id != NULL) {

- +				verbose("%s: The id already set in the PKCS#11 URI",

- +					__func__);

- +				rv = -1;

- +			}

- +			len = percent_decode(arg, &pkcs11->id);

- +			if (len <= 0) {

- +				verbose("%s: Failed to percent-decode CKA_ID: %s",

- +				    __func__, arg);

- +				rv = -1;

- +			} else

- +				pkcs11->id_len = len;

- +			debug3("%s: Setting CKA_ID = %s from PKCS#11 URI",

- +			    __func__, arg);

- +			break;

- +		case pToken:

- +			/* CK_TOKEN_INFO -> label */

- +			charptr = &pkcs11->token;

- + parse_string:

- +			if (*charptr != NULL) {

- +				verbose("%s: The %s already set in the PKCS#11 URI",

- +				    keywords[opcode].name, __func__);

- +				rv = -1;

- +			}

- +			percent_decode(arg, charptr);

- +			debug3("%s: Setting %s = %s from PKCS#11 URI",

- +			    __func__, keywords[opcode].name, *charptr);

- +			break;

- +

- +		case pObject:

- +			/* CK_TOKEN_INFO -> manufacturerID */

- +			charptr = &pkcs11->object;

- +			goto parse_string;

- +

- +		case pManufacturer:

- +			/* CK_TOKEN_INFO -> manufacturerID */

- +			charptr = &pkcs11->manuf;

- +			goto parse_string;

- +

- +		case pLibraryManufacturer:

- +			/* CK_INFO -> manufacturerID */

- +			charptr = &pkcs11->lib_manuf;

- +			goto parse_string;

- +

- +		case pBadOption:

- +		default:

- +			/* Unrecognized attribute in the URI path SHOULD be error */

- +			verbose("%s: Unknown part of path in PKCS#11 URI: %s",

- +			    __func__, tok);

- +		}

- +	}

- +

- +	tok = strtok_r(NULL, "?", &saveptr1);

- +	if (tok == NULL) {

- +		free(p);

- +		return rv;

- +	}

- +	/* parse pk11-query (optional) */

- +	for (str2 = tok; ; str2 = NULL) {

- +		size_t key_len = strlen(PKCS11_URI_MODULE_PATH) + 1;

- +		tok = strtok_r(str2, PKCS11_URI_QUERY_SEPARATOR, &saveptr2);

- +		if (tok == NULL)

- +			break;

- +		if (strncasecmp(tok, PKCS11_URI_MODULE_PATH

- +		    PKCS11_URI_VALUE_SEPARATOR, key_len) == 0) {

- +			/* module-path is PKCS11Provider */

- +			if (pkcs11->module_path != NULL) {

- +				verbose("%s: Multiple module-path attributes are"

- +				    "not supported the PKCS#11 URI", __func__);

- +				rv = -1;

- +			}

- +			percent_decode(tok + key_len, &pkcs11->module_path);

- +			debug3("%s: Setting PKCS11Provider = %s from PKCS#11 URI",

- +			    __func__, pkcs11->module_path);

- +		/* } else if ( pin-value ) { */

- +		} else {

- +			/* Unrecognized attribute in the URI query SHOULD be ignored */

- +			verbose("%s: Unknown part of query in PKCS#11 URI: %s",

- +			    __func__, tok);

- +		}

- +	}

- +	free(p);

- +	return rv;

- +}

- +

- +#endif /* ENABLE_PKCS11 */

- diff -up openssh/ssh-pkcs11-uri.h.pkcs11-uri openssh/ssh-pkcs11-uri.h

- --- openssh/ssh-pkcs11-uri.h.pkcs11-uri	2018-10-12 13:52:55.456191450 +0200

- +++ openssh/ssh-pkcs11-uri.h	2018-10-12 13:52:55.456191450 +0200

- @@ -0,0 +1,41 @@

- +/*

- + * Copyright (c) 2017 Red Hat

- + *

- + * Authors: Jakub Jelen <jjelen@redhat.com>

- + *

- + * Permission to use, copy, modify, and distribute this software for any

- + * purpose with or without fee is hereby granted, provided that the above

- + * copyright notice and this permission notice appear in all copies.

- + *

- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES

- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF

- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR

- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES

- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN

- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF

- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

- + */

- +

- +#define PKCS11_URI_SCHEME "pkcs11:"

- +#define PKCS11_URI_WHITELIST	"abcdefghijklmnopqrstuvwxyz" \

- +				"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \

- +				"0123456789_-.()"

- +

- +struct pkcs11_uri {

- +	/* path */

- +	char *id;

- +	size_t id_len;

- +	char *token;

- +	char *object;

- +	char *lib_manuf;

- +	char *manuf;

- +	/* query */

- +	char *module_path;

- +};

- +

- +struct pkcs11_uri *pkcs11_uri_init();

- +void pkcs11_uri_cleanup(struct pkcs11_uri *);

- +int	pkcs11_uri_parse(const char *, struct pkcs11_uri *);

- +struct pkcs11_uri *pkcs11_uri_init();

- +char * pkcs11_uri_get(struct pkcs11_uri *uri);

- +

file modified
+77 -108
@@ -154,20 +154,12 @@ 

   

   u_int	 dh_estimate(int);

   

- @@ -51,6 +52,7 @@ u_int	 dh_estimate(int);

-   * Miniumum increased in light of DH precomputation attacks.

-   */

-  #define DH_GRP_MIN	2048

- +#define DH_GRP_MIN_FIPS	2048

-  #define DH_GRP_MAX	8192

-  

-  /*

  diff -up openssh-7.9p1/entropy.c.fips openssh-7.9p1/entropy.c

  --- openssh-7.9p1/entropy.c.fips	2018-10-17 02:01:20.000000000 +0200

  +++ openssh-7.9p1/entropy.c	2019-03-11 17:06:37.621878041 +0100

  @@ -223,6 +223,11 @@ seed_rng(void)

-  		fatal("OpenSSL version mismatch. Built against %lx, you "

-  		    "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());

+  		    "have %lx", (u_long)OPENSSL_VERSION_NUMBER,

+  		    OpenSSL_version_num());

   

  +	/* clean the PRNG status when exiting the program */

  +#if OPENSSL_VERSION_NUMBER < 0x10100000L
@@ -175,13 +167,13 @@ 

  +#endif

  +

   #ifndef OPENSSL_PRNG_ONLY

-  	if (RAND_status() == 1) {

+  	if (RAND_status() == 1)

   		debug3("RNG is ready, skipping seeding");

  diff -up openssh-7.9p1/kex.c.fips openssh-7.9p1/kex.c

  --- openssh-7.9p1/kex.c.fips	2019-03-11 17:06:37.614877975 +0100

  +++ openssh-7.9p1/kex.c	2019-03-11 17:06:37.621878041 +0100

  @@ -122,6 +123,26 @@ static const struct kexalg kexalgs[] = {

-  	{ NULL, -1, -1, -1},

+  	{ NULL, -1, -1, -1 },

   };

   

  +static const struct kexalg kexalgs_fips[] = {
@@ -201,22 +193,22 @@ 

  +	    SSH_DIGEST_SHA512 },

  +# endif

  +#endif

- +	{ NULL, -1, -1, -1},

+ +	{ NULL, -1, -1, -1 },

  +};

  +

+  static char *

+  kex_alg_list_internal(char sep, const struct kexalg *algs)

+  {

+ @@ -129,7 +150,7 @@ kex_alg_list(char sep)

   char *

   kex_alg_list(char sep)

   {

- @@ -129,7 +150,7 @@ kex_alg_list(char sep)

-  	size_t nlen, rlen = 0;

-  	const struct kexalg *k;

+ -	return kex_alg_list_internal(sep, kexalgs);

+ +	return kex_alg_list_internal(sep, (FIPS_mode() ? kexalgs_fips : kexalgs));

+  }

   

- -	for (k = kexalgs; k->name != NULL; k++) {

- +	for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) {

-  		if (ret != NULL)

-  			ret[rlen++] = sep;

-  		nlen = strlen(k->name);

- @@ -149,7 +170,7 @@ kex_alg_by_name(const char *name)

+  char *

+ @@ -149,11 +170,11 @@ kex_alg_by_name(const char *name)

   {

   	const struct kexalg *k;

   
@@ -224,7 +216,13 @@ 

  +	for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) {

   		if (strcmp(k->name, name) == 0)

   			return k;

-  #ifdef GSSAPI

+ 	}

+ -	for (k = gss_kexalgs; k->name != NULL; k++) {

+ +	for (k = (FIPS_mode() ? NULL : gss_kexalgs); k->name != NULL; k++) {

+  		if (strncmp(k->name, name, strlen(k->name)) == 0)

+  			return k;

+  	}

+  	return NULL;

  @@ -175,7 +196,10 @@ kex_names_valid(const char *names)

   	for ((p = strsep(&cp, ",")); p && *p != '\0';

   	    (p = strsep(&cp, ","))) {
@@ -248,15 +246,6 @@ 

   #include <sys/types.h>

   

   #include <openssl/dh.h>

- @@ -65,7 +66,7 @@ kexgex_client(struct ssh *ssh)

-  

-  	nbits = dh_estimate(kex->dh_need * 8);

-  

- -	kex->min = DH_GRP_MIN;

- +	kex->min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN;

-  	kex->max = DH_GRP_MAX;

-  	kex->nbits = nbits;

-  	if (datafellows & SSH_BUG_DHGEX_LARGE)

  @@ -118,6 +119,10 @@ input_kex_dh_gex_group(int type, u_int32

   		r = SSH_ERR_ALLOC_FAIL;

   		goto out;
@@ -268,21 +257,6 @@ 

   	p = g = NULL; /* belong to kex->dh now */

   

   	/* generate and send 'e', client DH public key */

- diff -up openssh-7.9p1/kexgexs.c.fips openssh-7.9p1/kexgexs.c

- --- openssh-7.9p1/kexgexs.c.fips	2018-10-17 02:01:20.000000000 +0200

- +++ openssh-7.9p1/kexgexs.c	2019-03-11 17:06:37.621878041 +0100

- @@ -85,9 +85,9 @@ input_kex_dh_gex_request(int type, u_int

-  	kex->nbits = nbits;

-  	kex->min = min;

-  	kex->max = max;

- -	min = MAXIMUM(DH_GRP_MIN, min);

- +	min = MAXIMUM(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, min);

-  	max = MINIMUM(DH_GRP_MAX, max);

- -	nbits = MAXIMUM(DH_GRP_MIN, nbits);

- +	nbits = MAXIMUM(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, nbits);

-  	nbits = MINIMUM(DH_GRP_MAX, nbits);

-  

-  	if (kex->max < kex->min || kex->nbits < kex->min ||

  diff -up openssh-7.9p1/mac.c.fips openssh-7.9p1/mac.c

  --- openssh-7.9p1/mac.c.fips	2019-03-11 17:06:37.614877975 +0100

  +++ openssh-7.9p1/mac.c	2019-03-11 17:06:37.621878041 +0100
@@ -294,7 +268,7 @@ 

  +

   #include <string.h>

   #include <stdio.h>

-  

+  #include <stdlib.h>

  @@ -54,7 +56,7 @@ struct macalg {

   	int		etm;		/* Encrypt-then-MAC */

   };
@@ -376,7 +350,7 @@ 

  -	$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)

  +	$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)

   

-  ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o

+  ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o compat.o

  -	$(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)

  +	$(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)

   
@@ -464,15 +438,15 @@ 

  +		    all)) != 0) \

   			fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \

   	} while (0)

- -	ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher);

- -	ASSEMBLE(macs, KEX_SERVER_MAC, all_mac);

- -	ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);

+ -	ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, all_cipher);

+ -	ASSEMBLE(macs, KEX_CLIENT_MAC, all_mac);

+ -	ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, all_kex);

  -	ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);

  -	ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);

  -	ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);

- +	ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher);

- +	ASSEMBLE(macs, KEX_SERVER_MAC, KEX_FIPS_MAC, all_mac);

- +	ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, KEX_DEFAULT_KEX_FIPS, all_kex);

+ +	ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher);

+ +	ASSEMBLE(macs, KEX_CLIENT_MAC, KEX_FIPS_MAC, all_mac);

+ +	ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, KEX_DEFAULT_KEX_FIPS, all_kex);

  +	ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);

  +	ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);

  +	ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, KEX_FIPS_PK_ALG, all_sig);
@@ -553,14 +527,6 @@ 

   

   #ifndef HAVE_SETPROCTITLE

   	/* Prepare for later setproctitle emulation */

- @@ -1047,7 +1059,6 @@ main(int ac, char **av)

-  	host_arg = xstrdup(host);

-  

-  #ifdef WITH_OPENSSL

- -	OpenSSL_add_all_algorithms();

-  	ERR_load_crypto_strings();

-  #endif

-  

  @@ -1283,6 +1294,10 @@ main(int ac, char **av)

   

   	seed_rng();
@@ -569,9 +535,9 @@ 

  +		logit("FIPS mode initialized");

  +	}

  +

-  	if (options.user == NULL)

-  		options.user = xstrdup(pw->pw_name);

-  

+  	/*

+  	 * Discard other fds that are hanging around. These can cause problem

+  	 * with backgrounded ssh processes started by ControlPersist.

  diff -up openssh-7.9p1/sshconnect2.c.fips openssh-7.9p1/sshconnect2.c

  --- openssh-7.9p1/sshconnect2.c.fips	2019-03-11 17:06:37.580877655 +0100

  +++ openssh-7.9p1/sshconnect2.c	2019-03-11 17:06:37.623878060 +0100
@@ -584,7 +550,7 @@ 

   #include "openbsd-compat/sys-queue.h"

   

   #include "xmalloc.h"

- @@ -235,7 +237,8 @@ order_hostkeyalgs(char *host, struct soc

+ @@ -117,7 +117,8 @@ order_hostkeyalgs(char *host, struct soc

   	for (i = 0; i < options.num_system_hostfiles; i++)

   		load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);

   
@@ -594,71 +560,83 @@ 

   	maxlen = strlen(avail) + 1;

   	first = xmalloc(maxlen);

   	last = xmalloc(maxlen);

- @@ -290,23 +293,28 @@ ssh_kex2(char *host, struct sockaddr *ho

+ @@ -185,14 +185,16 @@ ssh_kex2(char *host, struct sockaddr *ho

+  	if (options.hostkeyalgorithms != NULL) {

+  		all_key = sshkey_alg_list(0, 0, 1, ',');

+  		if (kex_assemble_names(&options.hostkeyalgorithms,

+ -		    KEX_DEFAULT_PK_ALG, all_key) != 0)

+ +		    (FIPS_mode() ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG),

+ +		    all_key) != 0)

+  			fatal("%s: kex_assemble_namelist", __func__);

+  		free(all_key);

+  		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =

+  		    compat_pkalg_proposal(options.hostkeyalgorithms);

+  	} else {

+  		/* Enforce default */

+ -		options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG);

+ +		options.hostkeyalgorithms = xstrdup((FIPS_mode()

+ +		    ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG));

+  		/* Prefer algorithms that we already have keys for */

+  		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =

+  		    compat_pkalg_proposal(

+ @@ -201,29 +201,34 @@ ssh_kex2(char *host, struct sockaddr *ho

   

-  #ifdef GSSAPI

+  #if defined(GSSAPI) && defined(WITH_OPENSSL)

   	if (options.gss_keyex) {

- -		/* Add the GSSAPI mechanisms currently supported on this 

+ -		/* Add the GSSAPI mechanisms currently supported on this

  -		 * client to the key exchange algorithm proposal */

- -		orig = options.kex_algorithms;

+ -		orig = myproposal[PROPOSAL_KEX_ALGS];

  -

  -		if (options.gss_server_identity)

- -			gss_host = options.gss_server_identity;

+ -			gss_host = xstrdup(options.gss_server_identity);

  -		else if (options.gss_trust_dns)

- -			gss_host = (char *)get_canonical_hostname(active_state, 1);

+ -			gss_host = remote_hostname(ssh);

  -		else

- -			gss_host = host;

+ -			gss_host = xstrdup(host);

  -

  -		gss = ssh_gssapi_client_mechanisms(gss_host,

  -		    options.gss_client_identity, options.gss_kex_algorithms);

  -		if (gss) {

  -			debug("Offering GSSAPI proposal: %s", gss);

- -			xasprintf(&options.kex_algorithms,

+ -			xasprintf(&myproposal[PROPOSAL_KEX_ALGS],

  -			    "%s,%s", gss, orig);

+ -

+ -			/* If we've got GSSAPI algorithms, then we also support the

+ -			 * 'null' hostkey, as a last resort */

+ -			orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];

+ -			xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],

+ -			    "%s,null", orig);

  +		if (FIPS_mode()) {

  +			logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode");

  +			options.gss_keyex = 0;

  +		} else {

  +			/* Add the GSSAPI mechanisms currently supported on this

  +			 * client to the key exchange algorithm proposal */

- +			orig = options.kex_algorithms;

+ +			orig = myproposal[PROPOSAL_KEX_ALGS];

  +

  +			if (options.gss_server_identity)

- +				gss_host = options.gss_server_identity;

+ +				gss_host = xstrdup(options.gss_server_identity);

  +			else if (options.gss_trust_dns)

- +				gss_host = (char *)get_canonical_hostname(active_state, 1);

+ +				gss_host = remote_hostname(ssh);

  +			else

- +				gss_host = host;

+ +				gss_host = xstrdup(host);

  +

  +			gss = ssh_gssapi_client_mechanisms(gss_host,

  +			    options.gss_client_identity, options.gss_kex_algorithms);

  +			if (gss) {

  +				debug("Offering GSSAPI proposal: %s", gss);

- +				xasprintf(&options.kex_algorithms,

+ +				xasprintf(&myproposal[PROPOSAL_KEX_ALGS],

  +				    "%s,%s", gss, orig);

+ +

+ +				/* If we've got GSSAPI algorithms, then we also support the

+ +				 * 'null' hostkey, as a last resort */

+ +				orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];

+ +				xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],

+ +				    "%s,null", orig);

  +			}

   		}

   	}

   #endif

- @@ -326,14 +334,16 @@ ssh_kex2(char *host, struct sockaddr *ho

-  	if (options.hostkeyalgorithms != NULL) {

-  		all_key = sshkey_alg_list(0, 0, 1, ',');

-  		if (kex_assemble_names(&options.hostkeyalgorithms,

- -		    KEX_DEFAULT_PK_ALG, all_key) != 0)

- +		    (FIPS_mode() ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG),

- +		    all_key) != 0)

-  			fatal("%s: kex_assemble_namelist", __func__);

-  		free(all_key);

-  		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =

-  		    compat_pkalg_proposal(options.hostkeyalgorithms);

-  	} else {

-  		/* Enforce default */

- -		options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG);

- +		options.hostkeyalgorithms = xstrdup((FIPS_mode()

- +		    ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG));

-  		/* Prefer algorithms that we already have keys for */

-  		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =

-  		    compat_pkalg_proposal(

  diff -up openssh-7.9p1/sshd.c.fips openssh-7.9p1/sshd.c

  --- openssh-7.9p1/sshd.c.fips	2019-03-11 17:06:37.617878003 +0100

  +++ openssh-7.9p1/sshd.c	2019-03-11 17:06:37.624878069 +0100
@@ -698,15 +676,6 @@ 

   	/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */

   	saved_argc = ac;

   	rexec_argc = ac;

- @@ -1722,7 +1737,7 @@ main(int ac, char **av)

-  	else

-  		closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);

-  

- -#ifdef WITH_OPENSSL

- +#if 0 /* FIPS */

-  	OpenSSL_add_all_algorithms();

-  #endif

-  

  @@ -2036,6 +2051,10 @@ main(int ac, char **av)

   	/* Reinitialize the log (because of the fork above). */

   	log_init(__progname, options.log_level, options.log_facility, log_stderr);

@@ -411,7 +411,7 @@ 

   	}

   

   	krb5_free_principal(krb_context, princ);

- @@ -331,29 +332,19 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl

+ @@ -331,32 +332,21 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl

   	    client->creds, ccache))) {

   		logit("gss_krb5_copy_ccache() failed");

   		krb5_cc_destroy(krb_context, ccache);
@@ -425,6 +425,7 @@ 

  -	client->store.envvar = "KRB5CCNAME";

  -#ifdef USE_CCAPI

  -	xasprintf(&client->store.envval, "API:%s", new_ccname);

+ -	client->store.filename = NULL;

  -#else

  -	if (new_ccname[0] == ':')

  -		new_ccname++;
@@ -438,6 +439,8 @@ 

  +	if (set_env) {

  +		client->store.envvar = "KRB5CCNAME";

   	}

+  	if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0))

+  		client->store.filename = xstrdup(new_ccname);

  -#endif

   

   #ifdef USE_PAM
@@ -477,15 +480,16 @@ 

   }

   

   /* This allows GSSAPI methods to do things to the childs environment based

- @@ -496,8 +498,7 @@ ssh_gssapi_rekey_creds() {

+ @@ -498,9 +500,7 @@ ssh_gssapi_rekey_creds() {

   	char *envstr;

   #endif

   

- -	if (gssapi_client.store.envval == NULL &&

+ -	if (gssapi_client.store.filename == NULL &&

+ -	    gssapi_client.store.envval == NULL &&

  -	    gssapi_client.store.envvar == NULL)

  +	if (gssapi_client.store.envval == NULL)

   		return;

-   

+  

   	ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));

  diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c

  --- openssh-7.9p1/servconf.c.ccache_name	2019-03-01 15:17:42.704611768 +0100
@@ -590,14 +594,6 @@ 

  index 6593e422..245178af 100644

  --- a/ssh-gss.h

  +++ b/ssh-gss.h

- @@ -62,7 +62,6 @@

-  #define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"

-  

-  typedef struct {

- -	char *filename;

-  	char *envvar;

-  	char *envval;

-  	struct passwd *owner;

  @@ -83,7 +82,7 @@ typedef struct ssh_gssapi_mech_struct {

   	int (*dochild) (ssh_gssapi_client *);

   	int (*userok) (ssh_gssapi_client *, char *);

@@ -9,9 +9,9 @@ 

  +	if (! options.use_pam)

  +		logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems.");

  +

-  	seed_rng();

-  

   	/* Fill in default values for those options not explicitly set. */

+  	fill_default_server_options(&options);

+  

  diff --git a/sshd_config b/sshd_config

  --- a/sshd_config

  +++ b/sshd_config

file removed
-2905
@@ -1,2905 +0,0 @@ 

- diff -up openssh/auth2.c.gsskex openssh/auth2.c

- --- openssh/auth2.c.gsskex	2018-08-22 11:47:33.260216045 +0200

- +++ openssh/auth2.c	2018-08-22 11:47:33.307216424 +0200

- @@ -74,6 +74,7 @@ extern Authmethod method_passwd;

-  extern Authmethod method_kbdint;

-  extern Authmethod method_hostbased;

-  #ifdef GSSAPI

- +extern Authmethod method_gsskeyex;

-  extern Authmethod method_gssapi;

-  #endif

-  

- @@ -81,6 +82,7 @@ Authmethod *authmethods[] = {

-  	&method_none,

-  	&method_pubkey,

-  #ifdef GSSAPI

- +	&method_gsskeyex,

-  	&method_gssapi,

-  #endif

-  	&method_passwd,

- diff -up openssh/auth2-gss.c.gsskex openssh/auth2-gss.c

- --- openssh/auth2-gss.c.gsskex	2018-08-22 11:47:33.260216045 +0200

- +++ openssh/auth2-gss.c	2018-08-22 13:00:48.722680124 +0200

- @@ -31,6 +31,7 @@

-  #include <sys/types.h>

-  

-  #include <stdarg.h>

- +#include <string.h>

-  

-  #include "xmalloc.h"

-  #include "sshkey.h"

- @@ -54,6 +55,44 @@ static int input_gssapi_mic(int type, u_

-  static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh);

-  static int input_gssapi_errtok(int, u_int32_t, struct ssh *);

-  

- +/* 

- + * The 'gssapi_keyex' userauth mechanism.

- + */

- +static int

- +userauth_gsskeyex(struct ssh *ssh)

- +{

- +	Authctxt *authctxt = ssh->authctxt;

- +	int authenticated = 0;

- +	struct sshbuf *b = NULL;

- +	gss_buffer_desc mic, gssbuf;

- +	u_int len;

- +

- +	mic.value = packet_get_string(&len);

- +	mic.length = len;

- +

- +	packet_check_eom();

- +

- +	if ((b = sshbuf_new()) == NULL)

- +		fatal("%s: sshbuf_new failed", __func__);

- +

- +	ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,

- +	    "gssapi-keyex");

- +

- +	gssbuf.value = sshbuf_mutable_ptr(b);

- +	gssbuf.length = sshbuf_len(b);

- +

- +	/* gss_kex_context is NULL with privsep, so we can't check it here */

- +	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 

- +	    &gssbuf, &mic))))

- +		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,

- +		    authctxt->pw));

- +	

- +	sshbuf_free(b);

- +	free(mic.value);

- +

- +	return (authenticated);

- +}

- +

-  /*

-   * We only support those mechanisms that we know about (ie ones that we know

-   * how to check local user kuserok and the like)

- @@ -260,7 +296,8 @@ input_gssapi_exchange_complete(int type,

-  	if ((r = sshpkt_get_end(ssh)) != 0)

-  		fatal("%s: %s", __func__, ssh_err(r));

-  

- -	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));

- +	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,

- +	    authctxt->pw));

-  

-  	if ((!use_privsep || mm_is_monitor()) &&

-  	    (displayname = ssh_gssapi_displayname()) != NULL)

- @@ -313,7 +350,8 @@ input_gssapi_mic(int type, u_int32_t ple

-  	gssbuf.length = sshbuf_len(b);

-  

-  	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))

- -		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));

- +		authenticated = 

- +		    PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));

-  	else

-  		logit("GSSAPI MIC check failed");

-  

- @@ -335,6 +373,12 @@ input_gssapi_mic(int type, u_int32_t ple

-  	return 0;

-  }

-  

- +Authmethod method_gsskeyex = {

- +	"gssapi-keyex",

- +	userauth_gsskeyex,

- +	&options.gss_authentication

- +};

- +

-  Authmethod method_gssapi = {

-  	"gssapi-with-mic",

-  	userauth_gssapi,

- diff -up openssh/auth.c.gsskex openssh/auth.c

- --- openssh/auth.c.gsskex	2018-08-22 11:47:33.274216158 +0200

- +++ openssh/auth.c	2018-08-22 11:47:33.308216432 +0200

- @@ -395,6 +395,7 @@ auth_root_allowed(struct ssh *ssh, const

-  	case PERMIT_NO_PASSWD:

-  		if (strcmp(method, "publickey") == 0 ||

-  		    strcmp(method, "hostbased") == 0 ||

- +		    strcmp(method, "gssapi-keyex") == 0 ||

-  		    strcmp(method, "gssapi-with-mic") == 0)

-  			return 1;

-  		break;

- diff -up openssh/clientloop.c.gsskex openssh/clientloop.c

- --- openssh/clientloop.c.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/clientloop.c	2018-08-22 11:47:33.309216441 +0200

- @@ -112,6 +112,10 @@

-  #include "ssherr.h"

-  #include "hostfile.h"

-  

- +#ifdef GSSAPI

- +#include "ssh-gss.h"

- +#endif

- +

-  /* import options */

-  extern Options options;

-  

- @@ -1357,9 +1361,18 @@ client_loop(struct ssh *ssh, int have_pt

-  			break;

-  

-  		/* Do channel operations unless rekeying in progress. */

- -		if (!ssh_packet_is_rekeying(ssh))

- +		if (!ssh_packet_is_rekeying(ssh)) {

-  			channel_after_select(ssh, readset, writeset);

-  

- +#ifdef GSSAPI

- +			if (options.gss_renewal_rekey &&

- +			    ssh_gssapi_credentials_updated(NULL)) {

- +				debug("credentials updated - forcing rekey");

- +				need_rekeying = 1;

- +			}

- +#endif

- +		}

- +

-  		/* Buffer input from the connection.  */

-  		client_process_net_input(readset);

-  

- diff -up openssh/configure.ac.gsskex openssh/configure.ac

- --- openssh/configure.ac.gsskex	2018-08-22 11:47:33.296216335 +0200

- +++ openssh/configure.ac	2018-08-22 11:47:33.309216441 +0200

- @@ -673,6 +673,30 @@ main() { if (NSVersionOfRunTimeLibrary("

-  	    [Use tunnel device compatibility to OpenBSD])

-  	AC_DEFINE([SSH_TUN_PREPEND_AF], [1],

-  	    [Prepend the address family to IP tunnel traffic])

- +	AC_MSG_CHECKING(if we have the Security Authorization Session API)

- +	AC_TRY_COMPILE([#include <Security/AuthSession.h>],

- +		[SessionCreate(0, 0);],

- +		[ac_cv_use_security_session_api="yes"

- +		 AC_DEFINE(USE_SECURITY_SESSION_API, 1, 

- +			[platform has the Security Authorization Session API])

- +		 LIBS="$LIBS -framework Security"

- +		 AC_MSG_RESULT(yes)],

- +		[ac_cv_use_security_session_api="no"

- +		 AC_MSG_RESULT(no)])

- +	AC_MSG_CHECKING(if we have an in-memory credentials cache)

- +	AC_TRY_COMPILE(

- +		[#include <Kerberos/Kerberos.h>],

- +		[cc_context_t c;

- +		 (void) cc_initialize (&c, 0, NULL, NULL);],

- +		[AC_DEFINE(USE_CCAPI, 1, 

- +			[platform uses an in-memory credentials cache])

- +		 LIBS="$LIBS -framework Security"

- +		 AC_MSG_RESULT(yes)

- +		 if test "x$ac_cv_use_security_session_api" = "xno"; then

- +			AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***)

- +		fi],

- +		[AC_MSG_RESULT(no)]

- +	)

-  	m4_pattern_allow([AU_IPv])

-  	AC_CHECK_DECL([AU_IPv4], [],

-  	    AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])

- diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c

- --- openssh/gss-genr.c.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/gss-genr.c	2018-08-22 13:18:47.444383602 +0200

- @@ -35,18 +35,179 @@

-  #include <string.h>

-  #include <signal.h>

-  #include <unistd.h>

- +#include <openssl/evp.h>

-  

-  #include "xmalloc.h"

-  #include "ssherr.h"

-  #include "sshbuf.h"

-  #include "log.h"

-  #include "ssh2.h"

- +#include "cipher.h"

- +#include "sshkey.h"

- +#include "kex.h"

-  

-  #include "ssh-gss.h"

-  

-  extern u_char *session_id2;

-  extern u_int session_id2_len;

-  

- +typedef struct {

- +	char *encoded;

- +	gss_OID oid;

- +} ssh_gss_kex_mapping;

- +

- +/*

- + * XXX - It would be nice to find a more elegant way of handling the

- + * XXX   passing of the key exchange context to the userauth routines

- + */

- +

- +Gssctxt *gss_kex_context = NULL;

- +

- +static ssh_gss_kex_mapping *gss_enc2oid = NULL;

- +

- +int 

- +ssh_gssapi_oid_table_ok() {

- +	return (gss_enc2oid != NULL);

- +}

- +

- +/*

- + * Return a list of the gss-group1-sha1 mechanisms supported by this program

- + *

- + * We test mechanisms to ensure that we can use them, to avoid starting

- + * a key exchange with a bad mechanism

- + */

- +

- +char *

- +ssh_gssapi_client_mechanisms(const char *host, const char *client) {

- +	gss_OID_set gss_supported;

- +	OM_uint32 min_status;

- +

- +	if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))

- +		return NULL;

- +

- +	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,

- +	    host, client));

- +}

- +

- +char *

- +ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,

- +    const char *host, const char *client) {

- +	struct sshbuf *buf;

- +	size_t i;

- +	int oidpos, enclen, r;

- +	char *mechs, *encoded;

- +	u_char digest[EVP_MAX_MD_SIZE];

- +	char deroid[2];

- +	const EVP_MD *evp_md = EVP_md5();

- +	EVP_MD_CTX *md;

- +

- +	if (gss_enc2oid != NULL) {

- +		for (i = 0; gss_enc2oid[i].encoded != NULL; i++)

- +			free(gss_enc2oid[i].encoded);

- +		free(gss_enc2oid);

- +	}

- +

- +	gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *

- +	    (gss_supported->count + 1));

- +

- +	if ((buf = sshbuf_new()) == NULL)

- +		fatal("%s: sshbuf_new failed", __func__);

- +

- +	md = EVP_MD_CTX_new();

- +	oidpos = 0;

- +	for (i = 0; i < gss_supported->count; i++) {

- +		if (gss_supported->elements[i].length < 128 &&

- +		    (*check)(NULL, &(gss_supported->elements[i]), host, client)) {

- +

- +			deroid[0] = SSH_GSS_OIDTYPE;

- +			deroid[1] = gss_supported->elements[i].length;

- +

- +			EVP_DigestInit(md, evp_md);

- +			EVP_DigestUpdate(md, deroid, 2);

- +			EVP_DigestUpdate(md,

- +			    gss_supported->elements[i].elements,

- +			    gss_supported->elements[i].length);

- +			EVP_DigestFinal(md, digest, NULL);

- +

- +			encoded = xmalloc(EVP_MD_size(evp_md) * 2);

- +			enclen = __b64_ntop(digest, EVP_MD_size(evp_md),

- +			    encoded, EVP_MD_size(evp_md) * 2);

- +

- +			if (oidpos != 0)

- +				if ((r = sshbuf_put_u8(buf, ',')) != 0)

- +					fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +			if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID,

- +			    sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 ||

- +			    (r = sshbuf_put(buf, encoded, enclen)) != 0 ||

- +			    (r = sshbuf_put_u8(buf, ',')) != 0 ||

- +			    (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID, 

- +			    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 ||

- +			    (r = sshbuf_put(buf, encoded, enclen)) != 0 ||

- +			    (r = sshbuf_put_u8(buf, ',')) != 0 ||

- +			    (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID,

- +			    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 ||

- +			    (r = sshbuf_put(buf, encoded, enclen)) != 0)

- +		 		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +			gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);

- +			gss_enc2oid[oidpos].encoded = encoded;

- +			oidpos++;

- +		}

- +	}

- +	EVP_MD_CTX_free(md);

- +	gss_enc2oid[oidpos].oid = NULL;

- +	gss_enc2oid[oidpos].encoded = NULL;

- +

- +	if ((r = sshbuf_put_u8(buf, '\0')) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +	mechs = xmalloc(sshbuf_len(buf));

- +	sshbuf_get(buf, mechs, sshbuf_len(buf));

- +	sshbuf_free(buf);

- +

- +	if (strlen(mechs) == 0) {

- +		free(mechs);

- +		mechs = NULL;

- +	}

- +

- +	return (mechs);

- +}

- +

- +gss_OID

- +ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {

- +	int i = 0;

- +	

- +	switch (kex_type) {

- +	case KEX_GSS_GRP1_SHA1:

- +		if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))

- +			return GSS_C_NO_OID;

- +		name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;

- +		break;

- +	case KEX_GSS_GRP14_SHA1:

- +		if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))

- +			return GSS_C_NO_OID;

- +		name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;

- +		break;

- +	case KEX_GSS_GEX_SHA1:

- +		if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))

- +			return GSS_C_NO_OID;

- +		name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;

- +		break;

- +	default:

- +		return GSS_C_NO_OID;

- +	}

- +

- +	while (gss_enc2oid[i].encoded != NULL &&

- +	    strcmp(name, gss_enc2oid[i].encoded) != 0)

- +		i++;

- +

- +	if (gss_enc2oid[i].oid != NULL && ctx != NULL)

- +		ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);

- +

- +	return gss_enc2oid[i].oid;

- +}

- +

-  /* sshbuf_get for gss_buffer_desc */

-  int

-  ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g)

- @@ -218,7 +373,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de

-  	}

-  

-  	ctx->major = gss_init_sec_context(&ctx->minor,

- -	    GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,

- +	    ctx->client_creds, &ctx->context, ctx->name, ctx->oid,

-  	    GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,

-  	    0, NULL, recv_tok, NULL, send_tok, flags, NULL);

-  

- @@ -248,8 +403,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con

-  }

-  

-  OM_uint32

- +ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)

- +{

- +	gss_buffer_desc gssbuf;

- +	gss_name_t gssname;

- +	OM_uint32 status;

- +	gss_OID_set oidset;

- +

- +	gssbuf.value = (void *) name;

- +	gssbuf.length = strlen(gssbuf.value);

- +

- +	gss_create_empty_oid_set(&status, &oidset);

- +	gss_add_oid_set_member(&status, ctx->oid, &oidset);

- +

- +	ctx->major = gss_import_name(&ctx->minor, &gssbuf,

- +	    GSS_C_NT_USER_NAME, &gssname);

- +

- +	if (!ctx->major)

- +		ctx->major = gss_acquire_cred(&ctx->minor, 

- +		    gssname, 0, oidset, GSS_C_INITIATE, 

- +		    &ctx->client_creds, NULL, NULL);

- +

- +	gss_release_name(&status, &gssname);

- +	gss_release_oid_set(&status, &oidset);

- +

- +	if (ctx->major)

- +		ssh_gssapi_error(ctx);

- +

- +	return(ctx->major);

- +}

- +

- +OM_uint32

-  ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)

-  {

- +	if (ctx == NULL) 

- +		return -1;

- +

-  	if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,

-  	    GSS_C_QOP_DEFAULT, buffer, hash)))

-  		ssh_gssapi_error(ctx);

- @@ -257,6 +446,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer

-  	return (ctx->major);

-  }

-  

- +/* Priviledged when used by server */

- +OM_uint32

- +ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)

- +{

- +	if (ctx == NULL)

- +		return -1;

- +

- +	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,

- +	    gssbuf, gssmic, NULL);

- +

- +	return (ctx->major);

- +}

- +

-  void

-  ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service,

-      const char *context)

- @@ -273,11 +475,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, co

-  }

-  

-  int

- -ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)

- +ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 

- +    const char *client)

-  {

-  	gss_buffer_desc token = GSS_C_EMPTY_BUFFER;

-  	OM_uint32 major, minor;

-  	gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};

- +	Gssctxt *intctx = NULL;

- +

- +	if (ctx == NULL)

- +		ctx = &intctx;

-  

-  	/* RFC 4462 says we MUST NOT do SPNEGO */

-  	if (oid->length == spnego_oid.length && 

- @@ -287,6 +494,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx

-  	ssh_gssapi_build_ctx(ctx);

-  	ssh_gssapi_set_oid(*ctx, oid);

-  	major = ssh_gssapi_import_name(*ctx, host);

- +

- +	if (!GSS_ERROR(major) && client)

- +		major = ssh_gssapi_client_identity(*ctx, client);

- +

-  	if (!GSS_ERROR(major)) {

-  		major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 

-  		    NULL);

- @@ -296,10 +507,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx

-  			    GSS_C_NO_BUFFER);

-  	}

-  

- -	if (GSS_ERROR(major)) 

- +	if (GSS_ERROR(major) || intctx != NULL) 

-  		ssh_gssapi_delete_ctx(ctx);

-  

-  	return (!GSS_ERROR(major));

-  }

-  

- +int

- +ssh_gssapi_credentials_updated(Gssctxt *ctxt) {

- +	static gss_name_t saved_name = GSS_C_NO_NAME;

- +	static OM_uint32 saved_lifetime = 0;

- +	static gss_OID saved_mech = GSS_C_NO_OID;

- +	static gss_name_t name;

- +	static OM_uint32 last_call = 0;

- +	OM_uint32 lifetime, now, major, minor;

- +	int equal;

- +	

- +	now = time(NULL);

- +

- +	if (ctxt) {

- +		debug("Rekey has happened - updating saved versions");

- +

- +		if (saved_name != GSS_C_NO_NAME)

- +			gss_release_name(&minor, &saved_name);

- +

- +		major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,

- +		    &saved_name, &saved_lifetime, NULL, NULL);

- +

- +		if (!GSS_ERROR(major)) {

- +			saved_mech = ctxt->oid;

- +		        saved_lifetime+= now;

- +		} else {

- +			/* Handle the error */

- +		}

- +		return 0;

- +	}

- +

- +	if (now - last_call < 10)

- +		return 0;

- +

- +	last_call = now;

- +

- +	if (saved_mech == GSS_C_NO_OID)

- +		return 0;

- +	

- +	major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 

- +	    &name, &lifetime, NULL, NULL);

- +	if (major == GSS_S_CREDENTIALS_EXPIRED)

- +		return 0;

- +	else if (GSS_ERROR(major))

- +		return 0;

- +

- +	major = gss_compare_name(&minor, saved_name, name, &equal);

- +	gss_release_name(&minor, &name);

- +	if (GSS_ERROR(major))

- +		return 0;

- +

- +	if (equal && (saved_lifetime < lifetime + now - 10))

- +		return 1;

- +

- +	return 0;

- +}

- +

-  #endif /* GSSAPI */

- diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c

- --- openssh/gss-serv.c.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/gss-serv.c	2018-08-22 11:47:33.310216448 +0200

- @@ -44,17 +44,19 @@

-  #include "session.h"

-  #include "misc.h"

-  #include "servconf.h"

- +#include "uidswap.h"

-  

-  #include "ssh-gss.h"

- +#include "monitor_wrap.h"

-  

-  extern ServerOptions options;

-  

-  static ssh_gssapi_client gssapi_client =

- -    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,

- -    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}};

- +    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL,

- +    GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL}, 0, 0};

-  

-  ssh_gssapi_mech gssapi_null_mech =

- -    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};

- +    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};

-  

-  #ifdef KRB5

-  extern ssh_gssapi_mech gssapi_kerberos_mech;

- @@ -141,6 +143,28 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss

-  }

-  

-  /* Unprivileged */

- +char *

- +ssh_gssapi_server_mechanisms() {

- +	if (supported_oids == NULL)

- +		ssh_gssapi_prepare_supported_oids();

- +	return (ssh_gssapi_kex_mechs(supported_oids,

- +	    &ssh_gssapi_server_check_mech, NULL, NULL));

- +}

- +

- +/* Unprivileged */

- +int

- +ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,

- +    const char *dummy) {

- +	Gssctxt *ctx = NULL;

- +	int res;

- + 

- +	res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));

- +	ssh_gssapi_delete_ctx(&ctx);

- +

- +	return (res);

- +}

- +

- +/* Unprivileged */

-  void

-  ssh_gssapi_supported_oids(gss_OID_set *oidset)

-  {

- @@ -150,7 +174,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o

-  	gss_OID_set supported;

-  

-  	gss_create_empty_oid_set(&min_status, oidset);

- -	gss_indicate_mechs(&min_status, &supported);

- +

- +	if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))

- +		return;

-  

-  	while (supported_mechs[i]->name != NULL) {

-  		if (GSS_ERROR(gss_test_oid_set_member(&min_status,

- @@ -276,8 +302,48 @@ OM_uint32

-  ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)

-  {

-  	int i = 0;

- +	int equal = 0;

- +	gss_name_t new_name = GSS_C_NO_NAME;

- +	gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;

- +

- +	if (options.gss_store_rekey && client->used && ctx->client_creds) {

- +		if (client->mech->oid.length != ctx->oid->length ||

- +		    (memcmp(client->mech->oid.elements,

- +		     ctx->oid->elements, ctx->oid->length) !=0)) {

- +			debug("Rekeyed credentials have different mechanism");

- +			return GSS_S_COMPLETE;

- +		}

- +

- +		if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 

- +		    ctx->client_creds, ctx->oid, &new_name, 

- +		    NULL, NULL, NULL))) {

- +			ssh_gssapi_error(ctx);

- +			return (ctx->major);

- +		}

- +

- +		ctx->major = gss_compare_name(&ctx->minor, client->name, 

- +		    new_name, &equal);

- +

- +		if (GSS_ERROR(ctx->major)) {

- +			ssh_gssapi_error(ctx);

- +			return (ctx->major);

- +		}

- + 

- +		if (!equal) {

- +			debug("Rekeyed credentials have different name");

- +			return GSS_S_COMPLETE;

- +		}

- +

- +		debug("Marking rekeyed credentials for export");

-  

- -	gss_buffer_desc ename;

- +		gss_release_name(&ctx->minor, &client->name);

- +		gss_release_cred(&ctx->minor, &client->creds);

- +		client->name = new_name;

- +		client->creds = ctx->client_creds;

- +        	ctx->client_creds = GSS_C_NO_CREDENTIAL;

- +		client->updated = 1;

- +		return GSS_S_COMPLETE;

- +	}

-  

-  	client->mech = NULL;

-  

- @@ -292,6 +358,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g

-  	if (client->mech == NULL)

-  		return GSS_S_FAILURE;

-  

- +	if (ctx->client_creds &&

- +	    (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,

- +	     ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {

- +		ssh_gssapi_error(ctx);

- +		return (ctx->major);

- +	}

- +

-  	if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,

-  	    &client->displayname, NULL))) {

-  		ssh_gssapi_error(ctx);

- @@ -309,6 +382,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g

-  		return (ctx->major);

-  	}

-  

- +	gss_release_buffer(&ctx->minor, &ename);

- +

-  	/* We can't copy this structure, so we just move the pointer to it */

-  	client->creds = ctx->client_creds;

-  	ctx->client_creds = GSS_C_NO_CREDENTIAL;

- @@ -319,11 +394,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g

-  void

-  ssh_gssapi_cleanup_creds(void)

-  {

- -	if (gssapi_client.store.filename != NULL) {

- -		/* Unlink probably isn't sufficient */

- -		debug("removing gssapi cred file\"%s\"",

- -		    gssapi_client.store.filename);

- -		unlink(gssapi_client.store.filename);

- +	krb5_ccache ccache = NULL;

- +	krb5_error_code problem;

- +

- +	if (gssapi_client.store.data != NULL) {

- +		if ((problem = krb5_cc_resolve(gssapi_client.store.data, gssapi_client.store.envval, &ccache))) {

- +			debug("%s: krb5_cc_resolve(): %.100s", __func__,

- +				krb5_get_err_text(gssapi_client.store.data, problem));

- +		} else if ((problem = krb5_cc_destroy(gssapi_client.store.data, ccache))) {

- +			debug("%s: krb5_cc_destroy(): %.100s", __func__,

- +				krb5_get_err_text(gssapi_client.store.data, problem));

- +		} else {

- +			krb5_free_context(gssapi_client.store.data);

- +			gssapi_client.store.data = NULL;

- +		}

-  	}

-  }

-  

- @@ -356,7 +440,7 @@ ssh_gssapi_do_child(char ***envp, u_int

-  

-  /* Privileged */

-  int

- -ssh_gssapi_userok(char *user)

- +ssh_gssapi_userok(char *user, struct passwd *pw)

-  {

-  	OM_uint32 lmin;

-  

- @@ -366,9 +450,11 @@ ssh_gssapi_userok(char *user)

-  		return 0;

-  	}

-  	if (gssapi_client.mech && gssapi_client.mech->userok)

- -		if ((*gssapi_client.mech->userok)(&gssapi_client, user))

- +		if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {

- +			gssapi_client.used = 1;

- +			gssapi_client.store.owner = pw;

-  			return 1;

- -		else {

- +		} else {

-  			/* Destroy delegated credentials if userok fails */

-  			gss_release_buffer(&lmin, &gssapi_client.displayname);

-  			gss_release_buffer(&lmin, &gssapi_client.exportedname);

- @@ -382,14 +468,89 @@ ssh_gssapi_userok(char *user)

-  	return (0);

-  }

-  

- -/* Privileged */

- -OM_uint32

- -ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)

- +/* These bits are only used for rekeying. The unpriviledged child is running 

- + * as the user, the monitor is root.

- + *

- + * In the child, we want to :

- + *    *) Ask the monitor to store our credentials into the store we specify

- + *    *) If it succeeds, maybe do a PAM update

- + */

- +

- +/* Stuff for PAM */

- +

- +#ifdef USE_PAM

- +static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 

- +    struct pam_response **resp, void *data)

-  {

- -	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,

- -	    gssbuf, gssmic, NULL);

- +	return (PAM_CONV_ERR);

- +}

- +#endif

-  

- -	return (ctx->major);

- +void

- +ssh_gssapi_rekey_creds() {

- +	int ok;

- +	int ret;

- +#ifdef USE_PAM

- +	pam_handle_t *pamh = NULL;

- +	struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};

- +	char *envstr;

- +#endif

- +

- +	if (gssapi_client.store.envval == NULL &&

- +	    gssapi_client.store.envvar == NULL)

- +		return;

- + 

- +	ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));

- +

- +	if (!ok)

- +		return;

- +

- +	debug("Rekeyed credentials stored successfully");

- +

- +	/* Actually managing to play with the ssh pam stack from here will

- +	 * be next to impossible. In any case, we may want different options

- +	 * for rekeying. So, use our own :)

- +	 */

- +#ifdef USE_PAM	

- +	if (!use_privsep) {

- +		debug("Not even going to try and do PAM with privsep disabled");

- +		return;

- +	}

- +

- +	ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,

- + 	    &pamconv, &pamh);

- +	if (ret)

- +		return;

- +

- +	xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 

- +	    gssapi_client.store.envval);

- +

- +	ret = pam_putenv(pamh, envstr);

- +	if (!ret)

- +		pam_setcred(pamh, PAM_REINITIALIZE_CRED);

- +	pam_end(pamh, PAM_SUCCESS);

- +#endif

- +}

- +

- +int 

- +ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {

- +	int ok = 0;

- +

- +	/* Check we've got credentials to store */

- +	if (!gssapi_client.updated)

- +		return 0;

- +

- +	gssapi_client.updated = 0;

- +

- +	temporarily_use_uid(gssapi_client.store.owner);

- +	if (gssapi_client.mech && gssapi_client.mech->updatecreds)

- +		ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);

- +	else

- +		debug("No update function for this mechanism");

- +

- +	restore_uid();

- +

- +	return ok;

-  }

-  

-  /* Privileged */

- diff -up openssh/gss-serv-krb5.c.gsskex openssh/gss-serv-krb5.c

- --- openssh/gss-serv-krb5.c.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/gss-serv-krb5.c	2018-08-22 11:47:33.311216457 +0200

- @@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl

-  	krb5_error_code problem;

-  	krb5_principal princ;

-  	OM_uint32 maj_status, min_status;

- -	int len;

- +	const char *new_ccname, *new_cctype;

-  	const char *errmsg;

-  

-  	if (client->creds == NULL) {

- @@ -180,11 +180,23 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl

-  		return;

-  	}

-  

- -	client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));

- +	new_cctype = krb5_cc_get_type(krb_context, ccache);

- +	new_ccname = krb5_cc_get_name(krb_context, ccache);

- +

-  	client->store.envvar = "KRB5CCNAME";

- -	len = strlen(client->store.filename) + 6;

- -	client->store.envval = xmalloc(len);

- -	snprintf(client->store.envval, len, "FILE:%s", client->store.filename);

- +#ifdef USE_CCAPI

- +	xasprintf(&client->store.envval, "API:%s", new_ccname);

- +#else

- +	if (new_ccname[0] == ':')

- +		new_ccname++;

- +	xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname);

- +	if (strcmp(new_cctype, "DIR") == 0) {

- +		char *p;

- +		p = strrchr(client->store.envval, '/');

- +		if (p)

- +			*p = '\0';

- +	}

- +#endif

-  

-  #ifdef USE_PAM

-  	if (options.use_pam)

- @@ -193,9 +205,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl

-  

-  	krb5_cc_close(krb_context, ccache);

-  

- +	client->store.data = krb_context;

- +

-  	return;

-  }

-  

- +int

- +ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 

- +    ssh_gssapi_client *client)

- +{

- +	krb5_ccache ccache = NULL;

- +	krb5_principal principal = NULL;

- +	char *name = NULL;

- +	krb5_error_code problem;

- +	OM_uint32 maj_status, min_status;

- +

- +   	if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {

- +                logit("krb5_cc_resolve(): %.100s",

- +                    krb5_get_err_text(krb_context, problem));

- +                return 0;

- +       	}

- +	

- +	/* Find out who the principal in this cache is */

- +	if ((problem = krb5_cc_get_principal(krb_context, ccache, 

- +	    &principal))) {

- +		logit("krb5_cc_get_principal(): %.100s",

- +		    krb5_get_err_text(krb_context, problem));

- +		krb5_cc_close(krb_context, ccache);

- +		return 0;

- +	}

- +

- +	if ((problem = krb5_unparse_name(krb_context, principal, &name))) {

- +		logit("krb5_unparse_name(): %.100s",

- +		    krb5_get_err_text(krb_context, problem));

- +		krb5_free_principal(krb_context, principal);

- +		krb5_cc_close(krb_context, ccache);

- +		return 0;

- +	}

- +

- +

- +	if (strcmp(name,client->exportedname.value)!=0) {

- +		debug("Name in local credentials cache differs. Not storing");

- +		krb5_free_principal(krb_context, principal);

- +		krb5_cc_close(krb_context, ccache);

- +		krb5_free_unparsed_name(krb_context, name);

- +		return 0;

- +	}

- +	krb5_free_unparsed_name(krb_context, name);

- +

- +	/* Name matches, so lets get on with it! */

- +

- +	if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {

- +		logit("krb5_cc_initialize(): %.100s",

- +		    krb5_get_err_text(krb_context, problem));

- +		krb5_free_principal(krb_context, principal);

- +		krb5_cc_close(krb_context, ccache);

- +		return 0;

- +	}

- +

- +	krb5_free_principal(krb_context, principal);

- +

- +	if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,

- +	    ccache))) {

- +		logit("gss_krb5_copy_ccache() failed. Sorry!");

- +		krb5_cc_close(krb_context, ccache);

- +		return 0;

- +	}

- +

- +	return 1;

- +}

- +

-  ssh_gssapi_mech gssapi_kerberos_mech = {

-  	"toWM5Slw5Ew8Mqkay+al2g==",

-  	"Kerberos",

- @@ -203,7 +282,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {

-  	NULL,

-  	&ssh_gssapi_krb5_userok,

-  	NULL,

- -	&ssh_gssapi_krb5_storecreds

- +	&ssh_gssapi_krb5_storecreds,

- +	&ssh_gssapi_krb5_updatecreds

-  };

-  

-  #endif /* KRB5 */

- diff -up openssh/kex.c.gsskex openssh/kex.c

- --- openssh/kex.c.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/kex.c	2018-08-22 11:47:33.311216457 +0200

- @@ -54,6 +54,10 @@

-  #include "sshbuf.h"

-  #include "digest.h"

-  

- +#ifdef GSSAPI

- +#include "ssh-gss.h"

- +#endif

- +

-  /* prototype */

-  static int kex_choose_conf(struct ssh *);

-  static int kex_input_newkeys(int, u_int32_t, struct ssh *);

- @@ -103,6 +107,11 @@ static const struct kexalg kexalgs[] = {

-  	{ KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },

-  	{ KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },

-  #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */

- +#ifdef GSSAPI

- +	{ KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 },

- +	{ KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },

- +	{ KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },

- +#endif

-  	{ NULL, -1, -1, -1},

-  };

-  

- @@ -136,6 +145,12 @@ kex_alg_by_name(const char *name)

-  	for (k = kexalgs; k->name != NULL; k++) {

-  		if (strcmp(k->name, name) == 0)

-  			return k;

- +#ifdef GSSAPI

- +		if (strncmp(name, "gss-", 4) == 0) {

- +			if (strncmp(k->name, name, strlen(k->name)) == 0)

- +				return k;

- +		}

- +#endif

-  	}

-  	return NULL;

-  }

- diff -up openssh/kexgssc.c.gsskex openssh/kexgssc.c

- --- openssh/kexgssc.c.gsskex	2018-08-22 11:47:33.311216457 +0200

- +++ openssh/kexgssc.c	2018-08-22 11:47:33.311216457 +0200

- @@ -0,0 +1,341 @@

- +/*

- + * Copyright (c) 2001-2009 Simon Wilkinson. 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.

- + */

- +

- +#include "includes.h"

- +

- +#ifdef GSSAPI

- +

- +#include "includes.h"

- +

- +#include <openssl/crypto.h>

- +#include <openssl/bn.h>

- +

- +#include <string.h>

- +

- +#include "xmalloc.h"

- +#include "sshbuf.h"

- +#include "ssh2.h"

- +#include "sshkey.h"

- +#include "cipher.h"

- +#include "kex.h"

- +#include "log.h"

- +#include "packet.h"

- +#include "dh.h"

- +#include "digest.h"

- +

- +#include "ssh-gss.h"

- +

- +int

- +kexgss_client(struct ssh *ssh) {

- +	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;

- +	gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;

- +	Gssctxt *ctxt;

- +	OM_uint32 maj_status, min_status, ret_flags;

- +	u_int klen, kout, slen = 0, strlen;

- +	DH *dh; 

- +	BIGNUM *dh_server_pub = NULL;

- +	BIGNUM *shared_secret = NULL;

- +	BIGNUM *p = NULL;

- +	BIGNUM *g = NULL;	

- +	const BIGNUM *pub_key, *p1, *g1;

- +	u_char *kbuf;

- +	u_char *serverhostkey = NULL;

- +	u_char *empty = "";

- +	char *msg;

- +	char *lang;

- +	int type = 0;

- +	int first = 1;

- +	int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;

- +	u_char hash[SSH_DIGEST_MAX_LENGTH];

- +	size_t hashlen;

- +

- +	/* Initialise our GSSAPI world */	

- +	ssh_gssapi_build_ctx(&ctxt);

- +	if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type) 

- +	    == GSS_C_NO_OID)

- +		fatal("Couldn't identify host exchange");

- +

- +	if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host))

- +		fatal("Couldn't import hostname");

- +

- +	if (ssh->kex->gss_client && 

- +	    ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client))

- +		fatal("Couldn't acquire client credentials");

- +

- +	switch (ssh->kex->kex_type) {

- +	case KEX_GSS_GRP1_SHA1:

- +		dh = dh_new_group1();

- +		break;

- +	case KEX_GSS_GRP14_SHA1:

- +		dh = dh_new_group14();

- +		break;

- +	case KEX_GSS_GEX_SHA1:

- +		debug("Doing group exchange\n");

- +		nbits = dh_estimate(ssh->kex->we_need * 8);

- +		packet_start(SSH2_MSG_KEXGSS_GROUPREQ);

- +		packet_put_int(min);

- +		packet_put_int(nbits);

- +		packet_put_int(max);

- +

- +		packet_send();

- +

- +		packet_read_expect(SSH2_MSG_KEXGSS_GROUP);

- +

- +		if ((p = BN_new()) == NULL)

- +			fatal("BN_new() failed");

- +		packet_get_bignum2(p);

- +		if ((g = BN_new()) == NULL)

- +			fatal("BN_new() failed");

- +		packet_get_bignum2(g);

- +		packet_check_eom();

- +

- +		if (BN_num_bits(p) < min || BN_num_bits(p) > max)

- +			fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",

- +			    min, BN_num_bits(p), max);

- +

- +		dh = dh_new_group(g, p);

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);

- +	}

- +	

- +	/* Step 1 - e is pub_key */

- +	dh_gen_key(dh, ssh->kex->we_need * 8);

- +	DH_get0_key(dh, &pub_key, NULL);

- +

- +	/* This is f, we initialise it now to make life easier */

- +	dh_server_pub = BN_new();

- +	if (dh_server_pub == NULL)

- +		fatal("dh_server_pub == NULL");

- +

- +	token_ptr = GSS_C_NO_BUFFER;

- +			 

- +	do {

- +		debug("Calling gss_init_sec_context");

- +		

- +		maj_status = ssh_gssapi_init_ctx(ctxt,

- +		    ssh->kex->gss_deleg_creds, token_ptr, &send_tok,

- +		    &ret_flags);

- +

- +		if (GSS_ERROR(maj_status)) {

- +			if (send_tok.length != 0) {

- +				packet_start(SSH2_MSG_KEXGSS_CONTINUE);

- +				packet_put_string(send_tok.value,

- +				    send_tok.length);

- +			}

- +			fatal("gss_init_context failed");

- +		}

- +

- +		/* If we've got an old receive buffer get rid of it */

- +		if (token_ptr != GSS_C_NO_BUFFER)

- +			free(recv_tok.value);

- +

- +		if (maj_status == GSS_S_COMPLETE) {

- +			/* If mutual state flag is not true, kex fails */

- +			if (!(ret_flags & GSS_C_MUTUAL_FLAG))

- +				fatal("Mutual authentication failed");

- +

- +			/* If integ avail flag is not true kex fails */

- +			if (!(ret_flags & GSS_C_INTEG_FLAG))

- +				fatal("Integrity check failed");

- +		}

- +

- +		/* 

- +		 * If we have data to send, then the last message that we

- +		 * received cannot have been a 'complete'. 

- +		 */

- +		if (send_tok.length != 0) {

- +			if (first) {

- +				packet_start(SSH2_MSG_KEXGSS_INIT);

- +				packet_put_string(send_tok.value,

- +				    send_tok.length);

- +				packet_put_bignum2((BIGNUM *)pub_key);

- +				first = 0;

- +			} else {

- +				packet_start(SSH2_MSG_KEXGSS_CONTINUE);

- +				packet_put_string(send_tok.value,

- +				    send_tok.length);

- +			}

- +			packet_send();

- +			gss_release_buffer(&min_status, &send_tok);

- +

- +			/* If we've sent them data, they should reply */

- +			do {	

- +				type = packet_read();

- +				if (type == SSH2_MSG_KEXGSS_HOSTKEY) {

- +					debug("Received KEXGSS_HOSTKEY");

- +					if (serverhostkey)

- +						fatal("Server host key received more than once");

- +					serverhostkey = 

- +					    packet_get_string(&slen);

- +				}

- +			} while (type == SSH2_MSG_KEXGSS_HOSTKEY);

- +

- +			switch (type) {

- +			case SSH2_MSG_KEXGSS_CONTINUE:

- +				debug("Received GSSAPI_CONTINUE");

- +				if (maj_status == GSS_S_COMPLETE) 

- +					fatal("GSSAPI Continue received from server when complete");

- +				recv_tok.value = packet_get_string(&strlen);

- +				recv_tok.length = strlen; 

- +				break;

- +			case SSH2_MSG_KEXGSS_COMPLETE:

- +				debug("Received GSSAPI_COMPLETE");

- +				packet_get_bignum2(dh_server_pub);

- +				msg_tok.value =  packet_get_string(&strlen);

- +				msg_tok.length = strlen; 

- +

- +				/* Is there a token included? */

- +				if (packet_get_char()) {

- +					recv_tok.value=

- +					    packet_get_string(&strlen);

- +					recv_tok.length = strlen;

- +					/* If we're already complete - protocol error */

- +					if (maj_status == GSS_S_COMPLETE)

- +						packet_disconnect("Protocol error: received token when complete");

- +					} else {

- +						/* No token included */

- +						if (maj_status != GSS_S_COMPLETE)

- +							packet_disconnect("Protocol error: did not receive final token");

- +				}

- +				break;

- +			case SSH2_MSG_KEXGSS_ERROR:

- +				debug("Received Error");

- +				maj_status = packet_get_int();

- +				min_status = packet_get_int();

- +				msg = packet_get_string(NULL);

- +				lang = packet_get_string(NULL);

- +				fatal("GSSAPI Error: \n%.400s",msg);

- +			default:

- +				packet_disconnect("Protocol error: didn't expect packet type %d",

- +		    		type);

- +			}

- +			token_ptr = &recv_tok;

- +		} else {

- +			/* No data, and not complete */

- +			if (maj_status != GSS_S_COMPLETE)

- +				fatal("Not complete, and no token output");

- +		}

- +	} while (maj_status & GSS_S_CONTINUE_NEEDED);

- +

- +	/* 

- +	 * We _must_ have received a COMPLETE message in reply from the 

- +	 * server, which will have set dh_server_pub and msg_tok 

- +	 */

- +

- +	if (type != SSH2_MSG_KEXGSS_COMPLETE)

- +		fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");

- +

- +	/* Check f in range [1, p-1] */

- +	if (!dh_pub_is_valid(dh, dh_server_pub))

- +		packet_disconnect("bad server public DH value");

- +

- +	/* compute K=f^x mod p */

- +	klen = DH_size(dh);

- +	kbuf = xmalloc(klen);

- +	kout = DH_compute_key(kbuf, dh_server_pub, dh);

- +	if ((int)kout < 0)

- +		fatal("DH_compute_key: failed");

- +

- +	shared_secret = BN_new();

- +	if (shared_secret == NULL)

- +		fatal("kexgss_client: BN_new failed");

- +

- +	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)

- +		fatal("kexdh_client: BN_bin2bn failed");

- +

- +	memset(kbuf, 0, klen);

- +	free(kbuf);

- +

- +	hashlen = sizeof(hash);

- +	switch (ssh->kex->kex_type) {

- +	case KEX_GSS_GRP1_SHA1:

- +	case KEX_GSS_GRP14_SHA1:

- +		kex_dh_hash(ssh->kex->hash_alg, ssh->kex->client_version_string, 

- +		    ssh->kex->server_version_string,

- +		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),

- +		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),

- +		    (serverhostkey ? serverhostkey : empty), slen,

- +		    pub_key,		/* e */

- +		    dh_server_pub,	/* f */

- +		    shared_secret,	/* K */

- +		    hash, &hashlen

- +		);

- +		break;

- +	case KEX_GSS_GEX_SHA1:

- +		DH_get0_pqg(dh, &p1, NULL, &g1);

- +		kexgex_hash(

- +		    ssh->kex->hash_alg,

- +		    ssh->kex->client_version_string,

- +		    ssh->kex->server_version_string,

- +		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),

- +		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),

- +		    (serverhostkey ? serverhostkey : empty), slen,

- + 		    min, nbits, max,

- +		    p, g,

- +		    pub_key,

- +		    dh_server_pub,

- +		    shared_secret,

- +		    hash, &hashlen

- +		);

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);

- +	}

- +

- +	gssbuf.value = hash;

- +	gssbuf.length = hashlen;

- +

- +	/* Verify that the hash matches the MIC we just got. */

- +	if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))

- +		packet_disconnect("Hash's MIC didn't verify");

- +

- +	free(msg_tok.value);

- +

- +	DH_free(dh);

- +	if (serverhostkey)

- +		free(serverhostkey);

- +	BN_clear_free(dh_server_pub);

- +

- +	/* save session id */

- +	if (ssh->kex->session_id == NULL) {

- +		ssh->kex->session_id_len = hashlen;

- +		ssh->kex->session_id = xmalloc(ssh->kex->session_id_len);

- +		memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len);

- +	}

- +

- +	if (ssh->kex->gss_deleg_creds)

- +		ssh_gssapi_credentials_updated(ctxt);

- +

- +	if (gss_kex_context == NULL)

- +		gss_kex_context = ctxt;

- +	else

- +		ssh_gssapi_delete_ctx(&ctxt);

- +

- +	kex_derive_keys_bn(ssh, hash, hashlen, shared_secret);

- +	BN_clear_free(shared_secret);

- +	return kex_send_newkeys(ssh);

- +}

- +

- +#endif /* GSSAPI */

- diff -up openssh/kexgsss.c.gsskex openssh/kexgsss.c

- --- openssh/kexgsss.c.gsskex	2018-08-22 11:47:33.311216457 +0200

- +++ openssh/kexgsss.c	2018-08-22 11:47:33.311216457 +0200

- @@ -0,0 +1,300 @@

- +/*

- + * Copyright (c) 2001-2009 Simon Wilkinson. 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.

- + */

- +

- +#include "includes.h"

- +

- +#ifdef GSSAPI

- +

- +#include <string.h>

- +

- +#include <openssl/crypto.h>

- +#include <openssl/bn.h>

- +

- +#include "xmalloc.h"

- +#include "sshbuf.h"

- +#include "ssh2.h"

- +#include "sshkey.h"

- +#include "cipher.h"

- +#include "kex.h"

- +#include "log.h"

- +#include "packet.h"

- +#include "dh.h"

- +#include "ssh-gss.h"

- +#include "monitor_wrap.h"

- +#include "misc.h"      /* servconf.h needs misc.h for struct ForwardOptions */

- +#include "servconf.h"

- +#include "ssh-gss.h"

- +#include "digest.h"

- +

- +extern ServerOptions options;

- +

- +int

- +kexgss_server(struct ssh *ssh)

- +{

- +	OM_uint32 maj_status, min_status;

- +	

- +	/* 

- +	 * Some GSSAPI implementations use the input value of ret_flags (an

- + 	 * output variable) as a means of triggering mechanism specific 

- + 	 * features. Initializing it to zero avoids inadvertently 

- + 	 * activating this non-standard behaviour.

- +	 */

- +

- +	OM_uint32 ret_flags = 0;

- +	gss_buffer_desc gssbuf, recv_tok, msg_tok;

- +	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;

- +	Gssctxt *ctxt = NULL;

- +	u_int slen, klen, kout;

- +	u_char *kbuf;

- +	DH *dh;

- +	int min = -1, max = -1, nbits = -1;

- +	int cmin = -1, cmax = -1; /* client proposal */

- +	BIGNUM *shared_secret = NULL;

- +	BIGNUM *dh_client_pub = NULL;

- +	int type = 0;

- +	gss_OID oid;

- +	char *mechs;

- +	u_char hash[SSH_DIGEST_MAX_LENGTH];

- +	size_t hashlen;

- +	const BIGNUM *p, *g, *pub_key;

- +

- +	/* Initialise GSSAPI */

- +

- +	/* If we're rekeying, privsep means that some of the private structures

- +	 * in the GSSAPI code are no longer available. This kludges them back

- +	 * into life

- +	 */

- +	if (!ssh_gssapi_oid_table_ok()) 

- +		if ((mechs = ssh_gssapi_server_mechanisms()))

- +			free(mechs);

- +

- +	debug2("%s: Identifying %s", __func__, ssh->kex->name);

- +	oid = ssh_gssapi_id_kex(NULL, ssh->kex->name, ssh->kex->kex_type);

- +	if (oid == GSS_C_NO_OID)

- +	   fatal("Unknown gssapi mechanism");

- +

- +	debug2("%s: Acquiring credentials", __func__);

- +

- +	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))

- +		fatal("Unable to acquire credentials for the server");

- +

- +	switch (ssh->kex->kex_type) {

- +	case KEX_GSS_GRP1_SHA1:

- +		dh = dh_new_group1();

- +		break;

- +	case KEX_GSS_GRP14_SHA1:

- +		dh = dh_new_group14();

- +		break;

- +	case KEX_GSS_GEX_SHA1:

- +		debug("Doing group exchange");

- +		packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);

- +		/* store client proposal to provide valid signature */

- +		cmin = packet_get_int();

- +		nbits = packet_get_int();

- +		cmax = packet_get_int();

- +		min = MAX(DH_GRP_MIN, cmin);

- +		max = MIN(DH_GRP_MAX, cmax);

- +		packet_check_eom();

- +		if (max < min || nbits < min || max < nbits)

- +			fatal("GSS_GEX, bad parameters: %d !< %d !< %d",

- +			    min, nbits, max);

- +		dh = PRIVSEP(choose_dh(min, nbits, max));

- +		if (dh == NULL)

- +			packet_disconnect("Protocol error: no matching group found");

- +

- +		DH_get0_pqg(dh, &p, NULL, &g);

- +		packet_start(SSH2_MSG_KEXGSS_GROUP);

- +		packet_put_bignum2((BIGNUM *)p);

- +		packet_put_bignum2((BIGNUM *)g);

- +		packet_send();

- +

- +		packet_write_wait();

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);

- +	}

- +

- +	dh_gen_key(dh, ssh->kex->we_need * 8);

- +

- +	do {

- +		debug("Wait SSH2_MSG_GSSAPI_INIT");

- +		type = packet_read();

- +		switch(type) {

- +		case SSH2_MSG_KEXGSS_INIT:

- +			if (dh_client_pub != NULL) 

- +				fatal("Received KEXGSS_INIT after initialising");

- +			recv_tok.value = packet_get_string(&slen);

- +			recv_tok.length = slen; 

- +

- +			if ((dh_client_pub = BN_new()) == NULL)

- +				fatal("dh_client_pub == NULL");

- +

- +			packet_get_bignum2(dh_client_pub);

- +

- +			/* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */

- +			break;

- +		case SSH2_MSG_KEXGSS_CONTINUE:

- +			recv_tok.value = packet_get_string(&slen);

- +			recv_tok.length = slen; 

- +			break;

- +		default:

- +			packet_disconnect(

- +			    "Protocol error: didn't expect packet type %d",

- +			    type);

- +		}

- +

- +		maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 

- +		    &send_tok, &ret_flags));

- +

- +		free(recv_tok.value);

- +

- +		if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)

- +			fatal("Zero length token output when incomplete");

- +

- +		if (dh_client_pub == NULL)

- +			fatal("No client public key");

- +		

- +		if (maj_status & GSS_S_CONTINUE_NEEDED) {

- +			debug("Sending GSSAPI_CONTINUE");

- +			packet_start(SSH2_MSG_KEXGSS_CONTINUE);

- +			packet_put_string(send_tok.value, send_tok.length);

- +			packet_send();

- +			gss_release_buffer(&min_status, &send_tok);

- +		}

- +	} while (maj_status & GSS_S_CONTINUE_NEEDED);

- +

- +	if (GSS_ERROR(maj_status)) {

- +		if (send_tok.length > 0) {

- +			packet_start(SSH2_MSG_KEXGSS_CONTINUE);

- +			packet_put_string(send_tok.value, send_tok.length);

- +			packet_send();

- +		}

- +		fatal("accept_ctx died");

- +	}

- +

- +	if (!(ret_flags & GSS_C_MUTUAL_FLAG))

- +		fatal("Mutual Authentication flag wasn't set");

- +

- +	if (!(ret_flags & GSS_C_INTEG_FLAG))

- +		fatal("Integrity flag wasn't set");

- +	

- +	if (!dh_pub_is_valid(dh, dh_client_pub))

- +		packet_disconnect("bad client public DH value");

- +

- +	klen = DH_size(dh);

- +	kbuf = xmalloc(klen); 

- +	kout = DH_compute_key(kbuf, dh_client_pub, dh);

- +	if ((int)kout < 0)

- +		fatal("DH_compute_key: failed");

- +

- +	shared_secret = BN_new();

- +	if (shared_secret == NULL)

- +		fatal("kexgss_server: BN_new failed");

- +

- +	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)

- +		fatal("kexgss_server: BN_bin2bn failed");

- +

- +	memset(kbuf, 0, klen);

- +	free(kbuf);

- +

- +	DH_get0_key(dh, &pub_key, NULL);

- +	hashlen = sizeof(hash);

- +	switch (ssh->kex->kex_type) {

- +	case KEX_GSS_GRP1_SHA1:

- +	case KEX_GSS_GRP14_SHA1:

- +		kex_dh_hash(ssh->kex->hash_alg,

- +		    ssh->kex->client_version_string, ssh->kex->server_version_string,

- +		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),

- +		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),

- +		    NULL, 0, /* Change this if we start sending host keys */

- +		    dh_client_pub, pub_key, shared_secret,

- +		    hash, &hashlen

- +		);

- +		break;

- +	case KEX_GSS_GEX_SHA1:

- +		kexgex_hash(

- +		    ssh->kex->hash_alg,

- +		    ssh->kex->client_version_string, ssh->kex->server_version_string,

- +		    sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer),

- +		    sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my),

- +		    NULL, 0,

- +		    cmin, nbits, cmax,

- +		    p, g,

- +		    dh_client_pub,

- +		    pub_key,

- +		    shared_secret,

- +		    hash, &hashlen

- +		);

- +		break;

- +	default:

- +		fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);

- +	}

- +

- +	BN_clear_free(dh_client_pub);

- +

- +	if (ssh->kex->session_id == NULL) {

- +		ssh->kex->session_id_len = hashlen;

- +		ssh->kex->session_id = xmalloc(ssh->kex->session_id_len);

- +		memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len);

- +	}

- +

- +	gssbuf.value = hash;

- +	gssbuf.length = hashlen;

- +

- +	if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))

- +		fatal("Couldn't get MIC");

- +

- +	packet_start(SSH2_MSG_KEXGSS_COMPLETE);

- +	packet_put_bignum2(pub_key);

- +	packet_put_string(msg_tok.value,msg_tok.length);

- +

- +	if (send_tok.length != 0) {

- +		packet_put_char(1); /* true */

- +		packet_put_string(send_tok.value, send_tok.length);

- +	} else {

- +		packet_put_char(0); /* false */

- +	}

- +	packet_send();

- +

- +	gss_release_buffer(&min_status, &send_tok);

- +	gss_release_buffer(&min_status, &msg_tok);

- +

- +	if (gss_kex_context == NULL)

- +		gss_kex_context = ctxt;

- +	else 

- +		ssh_gssapi_delete_ctx(&ctxt);

- +

- +	DH_free(dh);

- +

- +	kex_derive_keys_bn(ssh, hash, hashlen, shared_secret);

- +	BN_clear_free(shared_secret);

- +	kex_send_newkeys(ssh);

- +

- +	/* If this was a rekey, then save out any delegated credentials we

- +	 * just exchanged.  */

- +	if (options.gss_store_rekey)

- +		ssh_gssapi_rekey_creds();

- +	return 0;

- +}

- +#endif /* GSSAPI */

- diff -up openssh/kex.h.gsskex openssh/kex.h

- --- openssh/kex.h.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/kex.h	2018-08-22 11:47:33.311216457 +0200

- @@ -100,6 +100,11 @@ enum kex_exchange {

-  	KEX_DH_GEX_SHA256,

-  	KEX_ECDH_SHA2,

-  	KEX_C25519_SHA256,

- +#ifdef GSSAPI

- +	KEX_GSS_GRP1_SHA1,

- +	KEX_GSS_GRP14_SHA1,

- +	KEX_GSS_GEX_SHA1,

- +#endif

-  	KEX_MAX

-  };

-  

- @@ -148,6 +153,12 @@ struct kex {

-  	u_int	flags;

-  	int	hash_alg;

-  	int	ec_nid;

- +#ifdef GSSAPI

- +	int	gss_deleg_creds;

- +	int	gss_trust_dns;

- +	char    *gss_host;

- +	char	*gss_client;

- +#endif

-  	char	*client_version_string;

-  	char	*server_version_string;

-  	char	*failed_choice;

- @@ -197,6 +208,10 @@ int	 kexecdh_client(struct ssh *);

-  int	 kexecdh_server(struct ssh *);

-  int	 kexc25519_client(struct ssh *);

-  int	 kexc25519_server(struct ssh *);

- +#ifdef GSSAPI

- +int	 kexgss_client(struct ssh *);

- +int	 kexgss_server(struct ssh *);

- +#endif

-  

-  int	 kex_dh_hash(int, const char *, const char *,

-      const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,

- diff -up openssh/Makefile.in.gsskex openssh/Makefile.in

- --- openssh/Makefile.in.gsskex	2018-08-22 11:47:33.312216465 +0200

- +++ openssh/Makefile.in	2018-08-22 13:19:54.955928277 +0200

- @@ -100,6 +100,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \

-  	readpass.o ttymodes.o xmalloc.o addrmatch.o \

-  	atomicio.o dispatch.o mac.o uuencode.o misc.o utf8.o \

-  	monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \

- +	kexgssc.o \

-  	msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \

-  	ssh-pkcs11.o smult_curve25519_ref.o \

-  	poly1305.o chacha.o cipher-chachapoly.o \

- @@ -121,7 +122,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw

-  	auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \

-  	auth2-none.o auth2-passwd.o auth2-pubkey.o \

-  	monitor.o monitor_wrap.o auth-krb5.o \

- -	auth2-gss.o gss-serv.o gss-serv-krb5.o \

- +	auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \

-  	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \

-  	sftp-server.o sftp-common.o \

-  	sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \

- diff -up openssh/monitor.c.gsskex openssh/monitor.c

- --- openssh/monitor.c.gsskex	2018-08-22 11:47:33.263216069 +0200

- +++ openssh/monitor.c	2018-08-22 13:22:19.589095240 +0200

- @@ -146,6 +146,8 @@ int mm_answer_gss_setup_ctx(int, struct

-  int mm_answer_gss_accept_ctx(int, struct sshbuf *);

-  int mm_answer_gss_userok(int, struct sshbuf *);

-  int mm_answer_gss_checkmic(int, struct sshbuf *);

- +int mm_answer_gss_sign(int, struct sshbuf *);

- +int mm_answer_gss_updatecreds(int, struct sshbuf *);

-  #endif

-  

-  #ifdef SSH_AUDIT_EVENTS

- @@ -219,11 +221,18 @@ struct mon_table mon_dispatch_proto20[]

-      {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},

-      {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok},

-      {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic},

- +    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},

-  #endif

-      {0, 0, NULL}

-  };

-  

-  struct mon_table mon_dispatch_postauth20[] = {

- +#ifdef GSSAPI

- +    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},

- +    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},

- +    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},

- +    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},

- +#endif

-  #ifdef WITH_OPENSSL

-      {MONITOR_REQ_MODULI, 0, mm_answer_moduli},

-  #endif

- @@ -293,6 +302,10 @@ monitor_child_preauth(Authctxt *_authctx

-  	/* Permit requests for moduli and signatures */

-  	monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);

-  	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);

- +#ifdef GSSAPI

- +	/* and for the GSSAPI key exchange */

- +	monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);

- +#endif

-  

-  	/* The first few requests do not require asynchronous access */

-  	while (!authenticated) {

- @@ -405,6 +418,10 @@ monitor_child_postauth(struct monitor *p

-  	monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);

-  	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);

-  	monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);

- +#ifdef GSSAPI

- +	/* and for the GSSAPI key exchange */

- +	monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);

- +#endif		

-  

-  	if (auth_opts->permit_pty_flag) {

-  		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);

- @@ -1695,6 +1712,13 @@ monitor_apply_keystate(struct monitor *p

-  # endif

-  #endif /* WITH_OPENSSL */

-  		kex->kex[KEX_C25519_SHA256] = kexc25519_server;

- +#ifdef GSSAPI

- +	if (options.gss_keyex) {

- +		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;

- +		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;

- +		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;

- +	}

- +#endif

-  		kex->load_host_public_key=&get_hostkey_public_by_type;

-  		kex->load_host_private_key=&get_hostkey_private_by_type;

-  		kex->host_key_index=&get_hostkey_index;

- @@ -1785,7 +1809,7 @@ mm_answer_gss_setup_ctx(int sock, struct

-  	u_char *p;

-  	int r;

-  

- -	if (!options.gss_authentication)

- +	if (!options.gss_authentication && !options.gss_keyex)

-  		fatal("%s: GSSAPI authentication not enabled", __func__);

-  

-  	if ((r = sshbuf_get_string(m, &p, &len)) != 0)

- @@ -1818,7 +1842,7 @@ mm_answer_gss_accept_ctx(int sock, struc

-  	OM_uint32 flags = 0; /* GSI needs this */

-  	int r;

-  

- -	if (!options.gss_authentication)

- +	if (!options.gss_authentication && !options.gss_keyex)

-  		fatal("%s: GSSAPI authentication not enabled", __func__);

-  

-  	if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0)

- @@ -1839,6 +1863,7 @@ mm_answer_gss_accept_ctx(int sock, struc

-  		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);

-  		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);

-  		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);

- +		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);

-  	}

-  	return (0);

-  }

- @@ -1850,7 +1875,7 @@ mm_answer_gss_checkmic(int sock, struct

-  	OM_uint32 ret;

-  	int r;

-  

- -	if (!options.gss_authentication)

- +	if (!options.gss_authentication && !options.gss_keyex)

-  		fatal("%s: GSSAPI authentication not enabled", __func__);

-  

-  	if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 ||

- @@ -1880,10 +1905,11 @@ mm_answer_gss_userok(int sock, struct ss

-  	int r, authenticated;

-  	const char *displayname;

-  

- -	if (!options.gss_authentication)

- +	if (!options.gss_authentication && !options.gss_keyex)

-  		fatal("%s: GSSAPI authentication not enabled", __func__);

-  

- -	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);

- +	authenticated = authctxt->valid &&

- +	    ssh_gssapi_userok(authctxt->user, authctxt->pw);

-  

-  	sshbuf_reset(m);

-  	if ((r = sshbuf_put_u32(m, authenticated)) != 0)

- @@ -1900,5 +1926,74 @@ mm_answer_gss_userok(int sock, struct ss

-  	/* Monitor loop will terminate if authenticated */

-  	return (authenticated);

-  }

- +

- +int 

- +mm_answer_gss_sign(int socket, struct sshbuf *m)

- +{

- +	gss_buffer_desc data;

- +	gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;

- +	OM_uint32 major, minor;

- +	int r;

- +

- +	if (!options.gss_authentication && !options.gss_keyex)

- +		fatal("In GSSAPI monitor when GSSAPI is disabled");

- +

- +	if ((r = sshbuf_get_string(m, (u_char **)&data.value, &data.length)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +	if (data.length != 20) 

- +		fatal("%s: data length incorrect: %d", __func__, 

- +		    (int) data.length);

- +

- +	/* Save the session ID on the first time around */

- +	if (session_id2_len == 0) {

- +		session_id2_len = data.length;

- +		session_id2 = xmalloc(session_id2_len);

- +		memcpy(session_id2, data.value, session_id2_len);

- +	}

- +	major = ssh_gssapi_sign(gsscontext, &data, &hash);

- +

- +	free(data.value);

- +

- +	sshbuf_reset(m);

- +	if ((r = sshbuf_put_u32(m, major)) != 0 ||

- +	    (r = sshbuf_put_string(m, hash.value, hash.length)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +	mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);

- +

- +	gss_release_buffer(&minor, &hash);

- +

- +	/* Turn on getpwnam permissions */

- +	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);

- +	

- +	/* And credential updating, for when rekeying */

- +	monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);

- +

- +	return (0);

- +}

- +

- +int

- +mm_answer_gss_updatecreds(int socket, struct sshbuf *m) {

- +	ssh_gssapi_ccache store;

- +	int ok, r;

- +

- +	if ((r = sshbuf_get_cstring(m, &store.envvar, NULL)) != 0 ||

- +	    (r = sshbuf_get_cstring(m, &store.envval, NULL)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +	ok = ssh_gssapi_update_creds(&store);

- +

- +	free(store.envvar);

- +	free(store.envval);

- +

- +	sshbuf_reset(m);

- +	if ((r = sshbuf_put_u32(m, ok)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +	mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);

- +

- +	return(0);

- +}

- +

-  #endif /* GSSAPI */

-  

- diff -up openssh/monitor.h.gsskex openssh/monitor.h

- --- openssh/monitor.h.gsskex	2018-08-22 11:47:33.263216069 +0200

- +++ openssh/monitor.h	2018-08-22 11:47:33.313216473 +0200

- @@ -58,6 +58,8 @@ enum monitor_reqtype {

-  #ifdef WITH_SELINUX

-  	MONITOR_REQ_AUTHROLE = 80,

-  #endif

- +	MONITOR_REQ_GSSSIGN = 82, MONITOR_ANS_GSSSIGN = 83,

- +	MONITOR_REQ_GSSUPCREDS = 84, MONITOR_ANS_GSSUPCREDS = 85,

-  

-  	MONITOR_REQ_PAM_START = 100,

-  	MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,

- diff -up openssh/monitor_wrap.c.gsskex openssh/monitor_wrap.c

- --- openssh/monitor_wrap.c.gsskex	2018-08-22 11:47:33.313216473 +0200

- +++ openssh/monitor_wrap.c	2018-08-22 13:27:38.665669643 +0200

- @@ -1004,7 +1004,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss

-  }

-  

-  int

- -mm_ssh_gssapi_userok(char *user)

- +mm_ssh_gssapi_userok(char *user, struct passwd *pw)

-  {

-  	struct sshbuf *m;

-  	int r, authenticated = 0;

- @@ -1023,4 +1023,52 @@ mm_ssh_gssapi_userok(char *user)

-  	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");

-  	return (authenticated);

-  }

- +

- +OM_uint32

- +mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)

- +{

- +	struct sshbuf *m;

- +	OM_uint32 major;

- +	int r;

- +

- +	if ((m = sshbuf_new()) == NULL)

- +		fatal("%s: sshbuf_new failed", __func__);

- +	if ((r = sshbuf_put_string(m, data->value, data->length)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, m);

- +	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, m);

- +

- +	if ((r = sshbuf_get_u32(m, &major)) != 0 ||

- +	    (r = sshbuf_get_string(m, (u_char **)&hash->value, &hash->length)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +	sshbuf_free(m);

- +

- +	return (major);

- +}

- +

- +int

- +mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)

- +{

- +	struct sshbuf *m;

- +	int ok, r;

- +

- +	if ((m = sshbuf_new()) == NULL)

- +		fatal("%s: sshbuf_new failed", __func__);

- +

- +	if ((r = sshbuf_put_cstring(m, store->envvar ? store->envvar : "")) != 0 ||

- +	    (r = sshbuf_put_cstring(m, store->envval ? store->envval : "")) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, m);

- +	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, m);

- +

- +	if ((r = sshbuf_get_u32(m, &ok)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

- +	sshbuf_free(m);

- +

- +	return (ok);

- +}

-  #endif /* GSSAPI */

- diff -up openssh/monitor_wrap.h.gsskex openssh/monitor_wrap.h

- --- openssh/monitor_wrap.h.gsskex	2018-08-22 11:47:33.263216069 +0200

- +++ openssh/monitor_wrap.h	2018-08-22 11:47:33.313216473 +0200

- @@ -63,8 +63,10 @@ int mm_sshkey_verify(const struct sshkey

-  OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);

-  OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,

-     gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);

- -int mm_ssh_gssapi_userok(char *user);

- +int mm_ssh_gssapi_userok(char *user, struct passwd *);

-  OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);

- +OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);

- +int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);

-  #endif

-  

-  #ifdef USE_PAM

- diff -up openssh/readconf.c.gsskex openssh/readconf.c

- --- openssh/readconf.c.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/readconf.c	2018-08-22 13:28:17.487982869 +0200

- @@ -161,6 +161,8 @@ typedef enum {

-  	oClearAllForwardings, oNoHostAuthenticationForLocalhost,

-  	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,

-  	oAddressFamily, oGssAuthentication, oGssDelegateCreds,

- +	oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,

- +	oGssServerIdentity, 

-  	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,

-  	oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,

-  	oHashKnownHosts,

- @@ -201,10 +203,19 @@ static struct {

-  	/* Sometimes-unsupported options */

-  #if defined(GSSAPI)

-  	{ "gssapiauthentication", oGssAuthentication },

- +	{ "gssapikeyexchange", oGssKeyEx },

-  	{ "gssapidelegatecredentials", oGssDelegateCreds },

- +	{ "gssapitrustdns", oGssTrustDns },

- +	{ "gssapiclientidentity", oGssClientIdentity },

- +	{ "gssapiserveridentity", oGssServerIdentity },

- +	{ "gssapirenewalforcesrekey", oGssRenewalRekey },

-  # else

-  	{ "gssapiauthentication", oUnsupported },

- +	{ "gssapikeyexchange", oUnsupported },

-  	{ "gssapidelegatecredentials", oUnsupported },

- +	{ "gssapitrustdns", oUnsupported },

- +	{ "gssapiclientidentity", oUnsupported },

- +	{ "gssapirenewalforcesrekey", oUnsupported },

-  #endif

-  #ifdef ENABLE_PKCS11

-  	{ "smartcarddevice", oPKCS11Provider },

- @@ -973,10 +984,30 @@ parse_time:

-  		intptr = &options->gss_authentication;

-  		goto parse_flag;

-  

- +	case oGssKeyEx:

- +		intptr = &options->gss_keyex;

- +		goto parse_flag;

- +

-  	case oGssDelegateCreds:

-  		intptr = &options->gss_deleg_creds;

-  		goto parse_flag;

-  

- +	case oGssTrustDns:

- +		intptr = &options->gss_trust_dns;

- +		goto parse_flag;

- +

- +	case oGssClientIdentity:

- +		charptr = &options->gss_client_identity;

- +		goto parse_string;

- +

- +	case oGssServerIdentity:

- +		charptr = &options->gss_server_identity;

- +		goto parse_string;

- +

- +	case oGssRenewalRekey:

- +		intptr = &options->gss_renewal_rekey;

- +		goto parse_flag;

- +

-  	case oBatchMode:

-  		intptr = &options->batch_mode;

-  		goto parse_flag;

- @@ -1817,7 +1848,12 @@ initialize_options(Options * options)

-  	options->pubkey_authentication = -1;

-  	options->challenge_response_authentication = -1;

-  	options->gss_authentication = -1;

- +	options->gss_keyex = -1;

-  	options->gss_deleg_creds = -1;

- +	options->gss_trust_dns = -1;

- +	options->gss_renewal_rekey = -1;

- +	options->gss_client_identity = NULL;

- +	options->gss_server_identity = NULL;

-  	options->password_authentication = -1;

-  	options->kbd_interactive_authentication = -1;

-  	options->kbd_interactive_devices = NULL;

- @@ -1962,8 +1998,14 @@ fill_default_options(Options * options)

-  		options->challenge_response_authentication = 1;

-  	if (options->gss_authentication == -1)

-  		options->gss_authentication = 0;

- +	if (options->gss_keyex == -1)

- +		options->gss_keyex = 0;

-  	if (options->gss_deleg_creds == -1)

-  		options->gss_deleg_creds = 0;

- +	if (options->gss_trust_dns == -1)

- +		options->gss_trust_dns = 0;

- +	if (options->gss_renewal_rekey == -1)

- +		options->gss_renewal_rekey = 0;

-  	if (options->password_authentication == -1)

-  		options->password_authentication = 1;

-  	if (options->kbd_interactive_authentication == -1)

- @@ -2603,7 +2645,12 @@ dump_client_config(Options *o, const cha

-  	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);

-  #ifdef GSSAPI

-  	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);

- +	dump_cfg_fmtint(oGssKeyEx, o->gss_keyex);

-  	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);

- +	dump_cfg_fmtint(oGssTrustDns, o->gss_trust_dns);

- +	dump_cfg_string(oGssClientIdentity, o->gss_client_identity);

- +	dump_cfg_string(oGssServerIdentity, o->gss_client_identity);

- +	dump_cfg_fmtint(oGssRenewalRekey, o->gss_renewal_rekey);

-  #endif /* GSSAPI */

-  	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);

-  	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);

- diff -up openssh-7.9p1/readconf.h.gsskex openssh-7.9p1/readconf.h

- --- openssh-7.9p1/readconf.h.gsskex	2018-10-17 02:01:20.000000000 +0200

- +++ openssh-7.9p1/readconf.h	2018-11-14 09:14:06.277379857 +0100

- @@ -40,7 +40,12 @@ typedef struct {

-  	int     challenge_response_authentication;

-  					/* Try S/Key or TIS, authentication. */

-  	int     gss_authentication;	/* Try GSS authentication */

- +	int     gss_keyex;		/* Try GSS key exchange */

-  	int     gss_deleg_creds;	/* Delegate GSS credentials */

- +	int	gss_trust_dns;		/* Trust DNS for GSS canonicalization */

- +	int	gss_renewal_rekey;	/* Credential renewal forces rekey */

- +	char    *gss_client_identity;   /* Principal to initiate GSSAPI with */

- +	char    *gss_server_identity;   /* GSSAPI target principal */

-  	int     password_authentication;	/* Try password

-  						 * authentication. */

-  	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */

- diff -up openssh/regress/cert-hostkey.sh.gsskex openssh/regress/cert-hostkey.sh

- --- openssh/regress/cert-hostkey.sh.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/regress/cert-hostkey.sh	2018-08-22 11:47:33.314216481 +0200

- @@ -66,7 +66,7 @@ touch $OBJ/host_revoked_plain

-  touch $OBJ/host_revoked_cert

-  cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca

-  

- -PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`

- +PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`

-  

-  if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then

-  	PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"

- diff -up openssh/regress/cert-userkey.sh.gsskex openssh/regress/cert-userkey.sh

- --- openssh/regress/cert-userkey.sh.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/regress/cert-userkey.sh	2018-08-22 11:47:33.314216481 +0200

- @@ -7,7 +7,7 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us

-  cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak

-  cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak

-  

- -PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`

- +PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`

-  EXTRA_TYPES=""

-  

-  if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then

- diff -up openssh/regress/kextype.sh.gsskex openssh/regress/kextype.sh

- --- openssh/regress/kextype.sh.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/regress/kextype.sh	2018-08-22 11:47:33.315216489 +0200

- @@ -14,6 +14,9 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/ssh

-  

-  tries="1 2 3 4"

-  for k in `${SSH} -Q kex`; do

- +	if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o $k = "gss-group14-sha1-" ]; then

- +		continue

- +	fi

-  	verbose "kex $k"

-  	for i in $tries; do

-  		${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true

- diff -up openssh/regress/rekey.sh.gsskex openssh/regress/rekey.sh

- --- openssh/regress/rekey.sh.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/regress/rekey.sh	2018-08-22 11:47:33.315216489 +0200

- @@ -38,6 +38,9 @@ increase_datafile_size 300

-  

-  opts=""

-  for i in `${SSH} -Q kex`; do

- +	if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o $i = "gss-group14-sha1-" ]; then

- +		continue

- +	fi

-  	opts="$opts KexAlgorithms=$i"

-  done

-  for i in `${SSH} -Q cipher`; do

- @@ -56,6 +59,9 @@ done

-  if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then

-    for c in `${SSH} -Q cipher-auth`; do

-      for kex in `${SSH} -Q kex`; do

- +	if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o $kex = "gss-group14-sha1-" ]; then

- +		continue

- +	fi

-  	verbose "client rekey $c $kex"

-  	ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c

-      done

- diff -up openssh/servconf.c.gsskex openssh/servconf.c

- --- openssh/servconf.c.gsskex	2018-08-22 11:47:33.296216335 +0200

- +++ openssh/servconf.c	2018-08-22 13:28:41.905179879 +0200

- @@ -124,8 +124,10 @@ initialize_server_options(ServerOptions

-  	options->kerberos_ticket_cleanup = -1;

-  	options->kerberos_get_afs_token = -1;

-  	options->gss_authentication=-1;

- +	options->gss_keyex = -1;

-  	options->gss_cleanup_creds = -1;

-  	options->gss_strict_acceptor = -1;

- +	options->gss_store_rekey = -1;

-  	options->password_authentication = -1;

-  	options->kbd_interactive_authentication = -1;

-  	options->challenge_response_authentication = -1;

- @@ -334,10 +336,14 @@ fill_default_server_options(ServerOption

-  		options->kerberos_get_afs_token = 0;

-  	if (options->gss_authentication == -1)

-  		options->gss_authentication = 0;

- +	if (options->gss_keyex == -1)

- +		options->gss_keyex = 0;

-  	if (options->gss_cleanup_creds == -1)

-  		options->gss_cleanup_creds = 1;

-  	if (options->gss_strict_acceptor == -1)

-  		options->gss_strict_acceptor = 1;

- +	if (options->gss_store_rekey == -1)

- +		options->gss_store_rekey = 0;

-  	if (options->password_authentication == -1)

-  		options->password_authentication = 1;

-  	if (options->kbd_interactive_authentication == -1)

- @@ -484,7 +490,7 @@ typedef enum {

-  	sHostKeyAlgorithms,

-  	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,

-  	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,

- -	sAcceptEnv, sSetEnv, sPermitTunnel,

- +	sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel,

-  	sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,

-  	sUsePrivilegeSeparation, sAllowAgentForwarding,

-  	sHostCertificate,

- @@ -559,11 +565,17 @@ static struct {

-  	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },

-  	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },

-  	{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },

- +	{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },

- +	{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },

-  #else

-  	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },

-  	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },

-  	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },

- +	{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },

- +	{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },

-  #endif

- +	{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },

- +	{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },

-  	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },

-  	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },

-  	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },

- @@ -1463,6 +1475,10 @@ process_server_config_line(ServerOptions

-  		intptr = &options->gss_authentication;

-  		goto parse_flag;

-  

- +	case sGssKeyEx:

- +		intptr = &options->gss_keyex;

- +		goto parse_flag;

- +

-  	case sGssCleanupCreds:

-  		intptr = &options->gss_cleanup_creds;

-  		goto parse_flag;

- @@ -1471,6 +1487,10 @@ process_server_config_line(ServerOptions

-  		intptr = &options->gss_strict_acceptor;

-  		goto parse_flag;

-  

- +	case sGssStoreRekey:

- +		intptr = &options->gss_store_rekey;

- +		goto parse_flag;

- +

-  	case sPasswordAuthentication:

-  		intptr = &options->password_authentication;

-  		goto parse_flag;

- @@ -2560,6 +2580,9 @@ dump_config(ServerOptions *o)

-  #ifdef GSSAPI

-  	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);

-  	dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);

- +	dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);

- +	dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);

- +	dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);

-  #endif

-  	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);

-  	dump_cfg_fmtint(sKbdInteractiveAuthentication,

- diff -up openssh/servconf.h.gsskex openssh/servconf.h

- --- openssh/servconf.h.gsskex	2018-08-22 11:47:33.296216335 +0200

- +++ openssh/servconf.h	2018-08-22 11:47:33.316216497 +0200

- @@ -124,8 +124,10 @@ typedef struct {

-  	int     kerberos_get_afs_token;		/* If true, try to get AFS token if

-  						 * authenticated with Kerberos. */

-  	int     gss_authentication;	/* If true, permit GSSAPI authentication */

- +	int     gss_keyex;		/* If true, permit GSSAPI key exchange */

-  	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */

-  	int     gss_strict_acceptor;	/* If true, restrict the GSSAPI acceptor name */

- +	int 	gss_store_rekey;

-  	int     password_authentication;	/* If true, permit password

-  						 * authentication. */

-  	int     kbd_interactive_authentication;	/* If true, permit */

- diff -up openssh/ssh_config.5.gsskex openssh/ssh_config.5

- --- openssh/ssh_config.5.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/ssh_config.5	2018-08-22 11:47:33.316216497 +0200

- @@ -718,10 +718,40 @@ The default is

-  Specifies whether user authentication based on GSSAPI is allowed.

-  The default is

-  .Cm no .

- +.It Cm GSSAPIClientIdentity

- +If set, specifies the GSSAPI client identity that ssh should use when 

- +connecting to the server. The default is unset, which means that the default 

- +identity will be used.

-  .It Cm GSSAPIDelegateCredentials

-  Forward (delegate) credentials to the server.

-  The default is

-  .Cm no .

- +.It Cm GSSAPIKeyExchange

- +Specifies whether key exchange based on GSSAPI may be used. When using

- +GSSAPI key exchange the server need not have a host key.

- +The default is

- +.Dq no .

- +.It Cm GSSAPIRenewalForcesRekey

- +If set to 

- +.Dq yes

- +then renewal of the client's GSSAPI credentials will force the rekeying of the

- +ssh connection. With a compatible server, this can delegate the renewed 

- +credentials to a session on the server.

- +The default is

- +.Dq no .

- +.It Cm GSSAPIServerIdentity

- +If set, specifies the GSSAPI server identity that ssh should expect when 

- +connecting to the server. The default is unset, which means that the

- +expected GSSAPI server identity will be determined from the target

- +hostname.

- +.It Cm GSSAPITrustDns

- +Set to 

- +.Dq yes to indicate that the DNS is trusted to securely canonicalize

- +the name of the host being connected to. If 

- +.Dq no, the hostname entered on the

- +command line will be passed untouched to the GSSAPI library.

- +The default is

- +.Dq no .

-  .It Cm HashKnownHosts

-  Indicates that

-  .Xr ssh 1

- diff -up openssh/ssh_config.gsskex openssh/ssh_config

- --- openssh/ssh_config.gsskex	2018-08-22 11:47:33.289216279 +0200

- +++ openssh/ssh_config	2018-08-22 11:47:33.316216497 +0200

- @@ -24,6 +24,8 @@

-  #   HostbasedAuthentication no

-  #   GSSAPIAuthentication no

-  #   GSSAPIDelegateCredentials no

- +#   GSSAPIKeyExchange no

- +#   GSSAPITrustDNS no

-  #   BatchMode no

-  #   CheckHostIP yes

-  #   AddressFamily any

- diff -up openssh/sshconnect2.c.gsskex openssh/sshconnect2.c

- --- openssh/sshconnect2.c.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/sshconnect2.c	2018-08-22 13:33:01.674275795 +0200

- @@ -82,6 +82,124 @@ extern char *client_version_string;

-  extern char *server_version_string;

-  extern Options options;

-  

- +/* XXX from auth.h -- refactoring move these useful functions away of client context*/

- +

- +/*

- + * Returns the remote DNS hostname as a string. The returned string must not

- + * be freed. NB. this will usually trigger a DNS query the first time it is

- + * called.

- + * This function does additional checks on the hostname to mitigate some

- + * attacks on legacy rhosts-style authentication.

- + * XXX is RhostsRSAAuthentication vulnerable to these?

- + * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)

- + */

- +

- +static char *

- +remote_hostname(struct ssh *ssh)

- +{

- +	struct sockaddr_storage from;

- +	socklen_t fromlen;

- +	struct addrinfo hints, *ai, *aitop;

- +	char name[NI_MAXHOST], ntop2[NI_MAXHOST];

- +	const char *ntop = ssh_remote_ipaddr(ssh);

- +

- +	/* Get IP address of client. */

- +	fromlen = sizeof(from);

- +	memset(&from, 0, sizeof(from));

- +	if (getpeername(ssh_packet_get_connection_in(ssh),

- +	    (struct sockaddr *)&from, &fromlen) < 0) {

- +		debug("getpeername failed: %.100s", strerror(errno));

- +		return strdup(ntop);

- +	}

- +

- +	ipv64_normalise_mapped(&from, &fromlen);

- +	if (from.ss_family == AF_INET6)

- +		fromlen = sizeof(struct sockaddr_in6);

- +

- +	debug3("Trying to reverse map address %.100s.", ntop);

- +	/* Map the IP address to a host name. */

- +	if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),

- +	    NULL, 0, NI_NAMEREQD) != 0) {

- +		/* Host name not found.  Use ip address. */

- +		return strdup(ntop);

- +	}

- +

- +	/*

- +	 * if reverse lookup result looks like a numeric hostname,

- +	 * someone is trying to trick us by PTR record like following:

- +	 *	1.1.1.10.in-addr.arpa.	IN PTR	2.3.4.5

- +	 */

- +	memset(&hints, 0, sizeof(hints));

- +	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/

- +	hints.ai_flags = AI_NUMERICHOST;

- +	if (getaddrinfo(name, NULL, &hints, &ai) == 0) {

- +		logit("Nasty PTR record \"%s\" is set up for %s, ignoring",

- +		    name, ntop);

- +		freeaddrinfo(ai);

- +		return strdup(ntop);

- +	}

- +

- +	/* Names are stored in lowercase. */

- +	lowercase(name);

- +

- +	/*

- +	 * Map it back to an IP address and check that the given

- +	 * address actually is an address of this host.  This is

- +	 * necessary because anyone with access to a name server can

- +	 * define arbitrary names for an IP address. Mapping from

- +	 * name to IP address can be trusted better (but can still be

- +	 * fooled if the intruder has access to the name server of

- +	 * the domain).

- +	 */

- +	memset(&hints, 0, sizeof(hints));

- +	hints.ai_family = from.ss_family;

- +	hints.ai_socktype = SOCK_STREAM;

- +	if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {

- +		logit("reverse mapping checking getaddrinfo for %.700s "

- +		    "[%s] failed.", name, ntop);

- +		return strdup(ntop);

- +	}

- +	/* Look for the address from the list of addresses. */

- +	for (ai = aitop; ai; ai = ai->ai_next) {

- +		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,

- +		    sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&

- +		    (strcmp(ntop, ntop2) == 0))

- +				break;

- +	}

- +	freeaddrinfo(aitop);

- +	/* If we reached the end of the list, the address was not there. */

- +	if (ai == NULL) {

- +		/* Address not found for the host name. */

- +		logit("Address %.100s maps to %.600s, but this does not "

- +		    "map back to the address.", ntop, name);

- +		return strdup(ntop);

- +	}

- +	return strdup(name);

- +}

- +

- +/*

- + * Return the canonical name of the host in the other side of the current

- + * connection.  The host name is cached, so it is efficient to call this

- + * several times.

- + */

- +

- +const char *

- +get_canonical_hostname(struct ssh *ssh, int use_dns)

- +{

- +	static char *dnsname;

- +

- +	if (!use_dns)

- +		return ssh_remote_ipaddr(ssh);

- +	else if (dnsname != NULL)

- +		return dnsname;

- +	else {

- +		dnsname = remote_hostname(ssh);

- +		return dnsname;

- +	}

- +}

- +

- +

- +

-  /*

-   * SSH2 key exchange

-   */

- @@ -162,9 +280,36 @@ ssh_kex2(char *host, struct sockaddr *ho

-  	struct kex *kex;

-  	int r;

-  

- +#ifdef GSSAPI

- +	char *orig = NULL, *gss = NULL;

- +	char *gss_host = NULL;

- +#endif

- +

-  	xxx_host = host;

-  	xxx_hostaddr = hostaddr;

-  

- +#ifdef GSSAPI

- +	if (options.gss_keyex) {

- +		/* Add the GSSAPI mechanisms currently supported on this 

- +		 * client to the key exchange algorithm proposal */

- +		orig = options.kex_algorithms;

- +

- +		if (options.gss_server_identity)

- +			gss_host = options.gss_server_identity;

- +		else if (options.gss_trust_dns)

- +			gss_host = (char *)get_canonical_hostname(active_state, 1);

- +		else

- +			gss_host = host;

- +

- +		gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);

- +		if (gss) {

- +			debug("Offering GSSAPI proposal: %s", gss);

- +			xasprintf(&options.kex_algorithms,

- +			    "%s,%s", gss, orig);

- +		}

- +	}

- +#endif

- +

-  	if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)

-  		fatal("%s: kex_names_cat", __func__);

-  	myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);

- @@ -194,6 +339,16 @@ ssh_kex2(char *host, struct sockaddr *ho

-  		    order_hostkeyalgs(host, hostaddr, port));

-  	}

-  

- +#ifdef GSSAPI

- +	/* If we've got GSSAPI algorithms, then we also support the

- +	 * 'null' hostkey, as a last resort */

- +	if (options.gss_keyex && gss) {

- +		orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];

- +		xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],

- +		    "%s,null", orig);

- +	}

- +#endif

- +

-  	if (options.rekey_limit || options.rekey_interval)

-  		packet_set_rekey_limits(options.rekey_limit,

-  		    options.rekey_interval);

- @@ -214,16 +369,46 @@ ssh_kex2(char *host, struct sockaddr *ho

-  	kex->kex[KEX_ECDH_SHA2] = kexecdh_client;

-  # endif

-  #endif

- +#ifdef GSSAPI

- +	if (options.gss_keyex) {

- +		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;

- +		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;

- +		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;

- +	}

- +#endif

-  	kex->kex[KEX_C25519_SHA256] = kexc25519_client;

-  	kex->client_version_string=client_version_string;

-  	kex->server_version_string=server_version_string;

-  	kex->verify_host_key=&verify_host_key_callback;

-  

- +#ifdef GSSAPI

- +	if (options.gss_keyex) {

- +		kex->gss_deleg_creds = options.gss_deleg_creds;

- +		kex->gss_trust_dns = options.gss_trust_dns;

- +		kex->gss_client = options.gss_client_identity;

- +		if (options.gss_server_identity) {

- +			kex->gss_host = options.gss_server_identity;

- +		} else {

- +			kex->gss_host = gss_host;

- +        }

- +	}

- +#endif

- +

-  	ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done);

-  

-  	/* remove ext-info from the KEX proposals for rekeying */

-  	myproposal[PROPOSAL_KEX_ALGS] =

-  	    compat_kex_proposal(options.kex_algorithms);

- +#ifdef GSSAPI

- +	/* repair myproposal after it was crumpled by the */

- +	/* ext-info removal above */

- +	if (gss) {

- +		orig = myproposal[PROPOSAL_KEX_ALGS];

- +		xasprintf(&myproposal[PROPOSAL_KEX_ALGS],

- +		    "%s,%s", gss, orig);

- +		free(gss);

- +	}

- +#endif

-  	if ((r = kex_prop2buf(kex->my, myproposal)) != 0)

-  		fatal("kex_prop2buf: %s", ssh_err(r));

-  

- @@ -314,6 +499,7 @@ int	input_gssapi_token(int type, u_int32

-  int	input_gssapi_hash(int type, u_int32_t, struct ssh *);

-  int	input_gssapi_error(int, u_int32_t, struct ssh *);

-  int	input_gssapi_errtok(int, u_int32_t, struct ssh *);

- +int	userauth_gsskeyex(Authctxt *authctxt);

-  #endif

-  

-  void	userauth(Authctxt *, char *);

- @@ -330,6 +505,11 @@ static char *authmethods_get(void);

-  

-  Authmethod authmethods[] = {

-  #ifdef GSSAPI

- +	{"gssapi-keyex",

- +		userauth_gsskeyex,

- +		NULL,

- +		&options.gss_authentication,

- +		NULL},

-  	{"gssapi-with-mic",

-  		userauth_gssapi,

-  		NULL,

- @@ -657,19 +837,31 @@ userauth_gssapi(Authctxt *authctxt)

-  	static u_int mech = 0;

-  	OM_uint32 min;

-  	int r, ok = 0;

- +	const char *gss_host;

- +

- +	if (options.gss_server_identity)

- +		gss_host = options.gss_server_identity;

- +	else if (options.gss_trust_dns)

- +		gss_host = get_canonical_hostname(active_state, 1);

- +	else

- +		gss_host = authctxt->host;

-  

-  	/* Try one GSSAPI method at a time, rather than sending them all at

-  	 * once. */

-  

-  	if (gss_supported == NULL)

- -		gss_indicate_mechs(&min, &gss_supported);

- +		if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {

- +			gss_supported = NULL;

- +			return 0;

- +		}

-  

-  	/* Check to see if the mechanism is usable before we offer it */

-  	while (mech < gss_supported->count && !ok) {

-  		/* My DER encoding requires length<128 */

-  		if (gss_supported->elements[mech].length < 128 &&

-  		    ssh_gssapi_check_mechanism(&gssctxt,

- -		    &gss_supported->elements[mech], authctxt->host)) {

- +		    &gss_supported->elements[mech], gss_host, 

- +                    options.gss_client_identity)) {

-  			ok = 1; /* Mechanism works */

-  		} else {

-  			mech++;

- @@ -906,6 +1098,51 @@ input_gssapi_error(int type, u_int32_t p

-  	free(lang);

-  	return r;

-  }

- +

- +int

- +userauth_gsskeyex(Authctxt *authctxt)

- +{

- +	struct sshbuf *b = NULL;

- +	gss_buffer_desc gssbuf;

- +	gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;

- +	OM_uint32 ms;

- +

- +	static int attempt = 0;

- +	if (attempt++ >= 1)

- +		return (0);

- +

- +	if (gss_kex_context == NULL) {

- +		debug("No valid Key exchange context"); 

- +		return (0);

- +	}

- +

- +	if ((b = sshbuf_new()) == NULL)

- +		fatal("%s: sshbuf_new failed", __func__);

- +

- +	ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service,

- +	    "gssapi-keyex");

- +

- +	gssbuf.value = sshbuf_mutable_ptr(b);

- +	gssbuf.length = sshbuf_len(b);

- +

- +	if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {

- +		sshbuf_free(b);

- +		return (0);

- +	}

- +

- +	packet_start(SSH2_MSG_USERAUTH_REQUEST);

- +	packet_put_cstring(authctxt->server_user);

- +	packet_put_cstring(authctxt->service);

- +	packet_put_cstring(authctxt->method->name);

- +	packet_put_string(mic.value, mic.length);

- +	packet_send();

- +

- +	sshbuf_free(b);

- +	gss_release_buffer(&ms, &mic);

- +

- +	return (1);

- +}

- +

-  #endif /* GSSAPI */

-  

-  int

- diff -up openssh/sshd.c.gsskex openssh/sshd.c

- --- openssh/sshd.c.gsskex	2018-08-22 11:47:33.299216360 +0200

- +++ openssh/sshd.c	2018-08-22 13:34:28.455975954 +0200

- @@ -887,8 +887,9 @@ notify_hostkeys(struct ssh *ssh)

-  	}

-  	debug3("%s: sent %u hostkeys", __func__, nkeys);

-  	if (nkeys == 0)

- -		fatal("%s: no hostkeys", __func__);

- -	packet_send();

- +		debug3("%s: no hostkeys", __func__);

- +	else

- +		packet_send();

-  	sshbuf_free(buf);

-  }

-  

- @@ -1841,7 +1842,8 @@ main(int ac, char **av)

-  		free(fp);

-  	}

-  	accumulate_host_timing_secret(cfg, NULL);

- -	if (!sensitive_data.have_ssh2_key) {

- +	/* The GSSAPI key exchange can run without a host key */

- +	if (!sensitive_data.have_ssh2_key && !options.gss_keyex) {

-  		logit("sshd: no hostkeys available -- exiting.");

-  		exit(1);

-  	}

- @@ -2321,6 +2323,48 @@ do_ssh2_kex(void)

-  	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(

-  	    list_hostkey_types());

-  

- +#ifdef GSSAPI

- +	{

- +	char *orig;

- +	char *gss = NULL;

- +	char *newstr = NULL;

- +	orig = myproposal[PROPOSAL_KEX_ALGS];

- +

- +	/* 

- +	 * If we don't have a host key, then there's no point advertising

- +	 * the other key exchange algorithms

- +	 */

- +

- +	if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)

- +		orig = NULL;

- +

- +	if (options.gss_keyex)

- +		gss = ssh_gssapi_server_mechanisms();

- +	else

- +		gss = NULL;

- +

- +	if (gss && orig)

- +		xasprintf(&newstr, "%s,%s", gss, orig);

- +	else if (gss)

- +		newstr = gss;

- +	else if (orig)

- +		newstr = orig;

- +

- +	/* 

- +	 * If we've got GSSAPI mechanisms, then we've got the 'null' host

- +	 * key alg, but we can't tell people about it unless its the only

- +  	 * host key algorithm we support

- +	 */

- +	if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)

- +		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";

- +

- +	if (newstr)

- +		myproposal[PROPOSAL_KEX_ALGS] = newstr;

- +	else

- +		fatal("No supported key exchange algorithms");

- +	}

- +#endif

- +

-  	/* start key exchange */

-  	if ((r = kex_setup(active_state, myproposal)) != 0)

-  		fatal("kex_setup: %s", ssh_err(r));

- @@ -2338,6 +2382,13 @@ do_ssh2_kex(void)

-  # endif

-  #endif

-  	kex->kex[KEX_C25519_SHA256] = kexc25519_server;

- +#ifdef GSSAPI

- +	if (options.gss_keyex) {

- +		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;

- +		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;

- +		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;

- +	}

- +#endif

-  	kex->server = 1;

-  	kex->client_version_string=client_version_string;

-  	kex->server_version_string=server_version_string;

- diff -up openssh/sshd_config.5.gsskex openssh/sshd_config.5

- --- openssh/sshd_config.5.gsskex	2018-08-22 11:47:33.297216344 +0200

- +++ openssh/sshd_config.5	2018-08-22 13:35:05.531275099 +0200

- @@ -642,6 +642,11 @@ Specifies whether to automatically destr

-  on logout.

-  The default is

-  .Cm yes .

- +.It Cm GSSAPIKeyExchange

- +Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange

- +doesn't rely on ssh keys to verify host identity.

- +The default is

- +.Dq no .

-  .It Cm GSSAPIStrictAcceptorCheck

-  Determines whether to be strict about the identity of the GSSAPI acceptor

-  a client authenticates against.

- @@ -656,6 +661,11 @@ machine's default store.

-  This facility is provided to assist with operation on multi homed machines.

-  The default is

-  .Cm yes .

- +.It Cm GSSAPIStoreCredentialsOnRekey

- +Controls whether the user's GSSAPI credentials should be updated following a 

- +successful connection rekeying. This option can be used to accepted renewed 

- +or updated credentials from a compatible client. The default is

- +.Dq no .

-  .It Cm HostbasedAcceptedKeyTypes

-  Specifies the key types that will be accepted for hostbased authentication

-  as a list of comma-separated patterns.

- diff -up openssh/sshd_config.gsskex openssh/sshd_config

- --- openssh/sshd_config.gsskex	2018-08-22 11:47:33.299216360 +0200

- +++ openssh/sshd_config	2018-08-22 11:47:33.318216513 +0200

- @@ -85,6 +85,8 @@ ChallengeResponseAuthentication no

-  # GSSAPI options

-  GSSAPIAuthentication yes

-  GSSAPICleanupCredentials no

- +#GSSAPIStrictAcceptorCheck yes

- +#GSSAPIKeyExchange no

-  

-  # Set this to 'yes' to enable PAM authentication, account processing,

-  # and session processing. If this is enabled, PAM authentication will

- diff -up openssh/ssh-gss.h.gsskex openssh/ssh-gss.h

- --- openssh/ssh-gss.h.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/ssh-gss.h	2018-08-22 13:36:44.773075793 +0200

- @@ -1,6 +1,6 @@

-  /* $OpenBSD: ssh-gss.h,v 1.14 2018/07/10 09:13:30 djm Exp $ */

-  /*

- - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.

- + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.

-   *

-   * Redistribution and use in source and binary forms, with or without

-   * modification, are permitted provided that the following conditions

- @@ -61,10 +61,22 @@

-  

-  #define SSH_GSS_OIDTYPE 0x06

-  

- +#define SSH2_MSG_KEXGSS_INIT                            30

- +#define SSH2_MSG_KEXGSS_CONTINUE                        31

- +#define SSH2_MSG_KEXGSS_COMPLETE                        32

- +#define SSH2_MSG_KEXGSS_HOSTKEY                         33

- +#define SSH2_MSG_KEXGSS_ERROR                           34

- +#define SSH2_MSG_KEXGSS_GROUPREQ			40

- +#define SSH2_MSG_KEXGSS_GROUP				41

- +#define KEX_GSS_GRP1_SHA1_ID				"gss-group1-sha1-"

- +#define KEX_GSS_GRP14_SHA1_ID				"gss-group14-sha1-"

- +#define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"

- +

-  typedef struct {

-  	char *filename;

-  	char *envvar;

-  	char *envval;

- +	struct passwd *owner;

-  	void *data;

-  } ssh_gssapi_ccache;

-  

- @@ -72,8 +84,11 @@ typedef struct {

-  	gss_buffer_desc displayname;

-  	gss_buffer_desc exportedname;

-  	gss_cred_id_t creds;

- +	gss_name_t name;

-  	struct ssh_gssapi_mech_struct *mech;

-  	ssh_gssapi_ccache store;

- +	int used;

- +	int updated;

-  } ssh_gssapi_client;

-  

-  typedef struct ssh_gssapi_mech_struct {

- @@ -84,6 +99,7 @@ typedef struct ssh_gssapi_mech_struct {

-  	int (*userok) (ssh_gssapi_client *, char *);

-  	int (*localname) (ssh_gssapi_client *, char **);

-  	void (*storecreds) (ssh_gssapi_client *);

- +	int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);

-  } ssh_gssapi_mech;

-  

-  typedef struct {

- @@ -94,10 +110,11 @@ typedef struct {

-  	gss_OID		oid; /* client */

-  	gss_cred_id_t	creds; /* server */

-  	gss_name_t	client; /* server */

- -	gss_cred_id_t	client_creds; /* server */

- +	gss_cred_id_t	client_creds; /* both */

-  } Gssctxt;

-  

-  extern ssh_gssapi_mech *supported_mechs[];

- +extern Gssctxt *gss_kex_context;

-  

-  int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);

-  void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);

- @@ -123,17 +140,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **);

-  OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);

-  void ssh_gssapi_buildmic(struct sshbuf *, const char *,

-      const char *, const char *);

- -int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);

- +int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);

- +OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);

- +int ssh_gssapi_credentials_updated(Gssctxt *);

-  

-  /* In the server */

- +typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 

- +    const char *);

- +char *ssh_gssapi_client_mechanisms(const char *, const char *);

- +char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,

- +    const char *);

- +gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);

- +int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 

- +    const char *);

-  OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);

- -int ssh_gssapi_userok(char *name);

- +int ssh_gssapi_userok(char *name, struct passwd *);

-  OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);

-  void ssh_gssapi_do_child(char ***, u_int *);

-  void ssh_gssapi_cleanup_creds(void);

-  void ssh_gssapi_storecreds(void);

-  const char *ssh_gssapi_displayname(void);

-  

- +char *ssh_gssapi_server_mechanisms(void);

- +int ssh_gssapi_oid_table_ok();

- +

- +int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);

- +

- +void ssh_gssapi_rekey_creds(void);

-  #endif /* GSSAPI */

-  

-  #endif /* _SSH_GSS_H */

- diff -up openssh/sshkey.c.gsskex openssh/sshkey.c

- --- openssh/sshkey.c.gsskex	2018-08-22 11:47:33.319216521 +0200

- +++ openssh/sshkey.c	2018-08-22 13:37:18.979351804 +0200

- @@ -140,6 +140,7 @@ static const struct keytype keytypes[] =

-  #  endif /* OPENSSL_HAS_NISTP521 */

-  # endif /* OPENSSL_HAS_ECC */

-  #endif /* WITH_OPENSSL */

- +	{ "null", "null", NULL, KEY_NULL, 0, 0, 1 },

-  	{ NULL, NULL, NULL, -1, -1, 0, 0 }

-  };

-  

- diff -up openssh/sshkey.h.gsskex openssh/sshkey.h

- --- openssh/sshkey.h.gsskex	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/sshkey.h	2018-08-22 11:47:33.320216529 +0200

- @@ -63,6 +63,7 @@ enum sshkey_types {

-  	KEY_ED25519_CERT,

-  	KEY_XMSS,

-  	KEY_XMSS_CERT,

- +	KEY_NULL,

-  	KEY_UNSPEC

-  };

-  

@@ -1,72 +0,0 @@ 

- diff -up openssh/misc.c.config openssh/misc.c

- --- openssh/misc.c.config	2018-08-22 13:58:54.922807799 +0200

- +++ openssh/misc.c	2018-08-22 13:58:55.000808428 +0200

- @@ -485,7 +485,7 @@ put_host_port(const char *host, u_short

-   * The delimiter char, if present, is stored in delim.

-   * If this is the last field, *cp is set to NULL.

-   */

- -static char *

- +char *

-  hpdelim2(char **cp, char *delim)

-  {

-  	char *s, *old;

- diff -up openssh/misc.h.config openssh/misc.h

- --- openssh/misc.h.config	2018-08-20 07:57:29.000000000 +0200

- +++ openssh/misc.h	2018-08-22 13:58:55.001808436 +0200

- @@ -54,6 +54,7 @@ int	 set_rdomain(int, const char *);

-  int	 a2port(const char *);

-  int	 a2tun(const char *, int *);

-  char	*put_host_port(const char *, u_short);

- +char	*hpdelim2(char **, char *);

-  char	*hpdelim(char **);

-  char	*cleanhostname(char *);

-  char	*colon(char *);

- diff -up openssh/servconf.c.config openssh/servconf.c

- --- openssh/servconf.c.config	2018-08-22 13:58:54.989808340 +0200

- +++ openssh/servconf.c	2018-08-22 14:18:49.235443937 +0200

- @@ -886,7 +886,7 @@ process_permitopen_list(struct ssh *ssh,

-  {

-  	u_int i;

-  	int port;

- -	char *host, *arg, *oarg;

- +	char *host, *arg, *oarg, ch;

-  	int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE;

-  	const char *what = lookup_opcode_name(opcode);

-  

- @@ -904,8 +904,8 @@ process_permitopen_list(struct ssh *ssh,

-  	/* Otherwise treat it as a list of permitted host:port */

-  	for (i = 0; i < num_opens; i++) {

-  		oarg = arg = xstrdup(opens[i]);

- -		host = hpdelim(&arg);

- -		if (host == NULL)

- +		host = hpdelim2(&arg, &ch);

- +		if (host == NULL || ch == '/')

-  			fatal("%s: missing host in %s", __func__, what);

-  		host = cleanhostname(host);

-  		if (arg == NULL || ((port = permitopen_port(arg)) < 0))

- @@ -1323,8 +1323,10 @@ process_server_config_line(ServerOptions

-  			port = 0;

-  			p = arg;

-  		} else {

- -			p = hpdelim(&arg);

- -			if (p == NULL)

- +			char ch;

- +			arg2 = NULL;

- +			p = hpdelim2(&arg, &ch);

- +			if (p == NULL || ch == '/')

-  				fatal("%s line %d: bad address:port usage",

-  				    filename, linenum);

-  			p = cleanhostname(p);

- @@ -1965,9 +1967,10 @@ process_server_config_line(ServerOptions

-  				 */

-  				xasprintf(&arg2, "*:%s", arg);

-  			} else {

- +				char ch;

-  				arg2 = xstrdup(arg);

- -				p = hpdelim(&arg);

- -				if (p == NULL) {

- +				p = hpdelim2(&arg, &ch);

- +				if (p == NULL || ch == '/') {

-  					fatal("%s line %d: missing host in %s",

-  					    filename, linenum,

-  					    lookup_opcode_name(opcode));

file modified
+18 -18
@@ -4,11 +4,11 @@ 

  @@ -256,6 +256,9 @@ input_userauth_request(int type, u_int32

   	Authctxt *authctxt = ssh->authctxt;

   	Authmethod *m = NULL;

-  	char *user, *service, *method, *style = NULL;

+  	char *user = NULL, *service = NULL, *method = NULL, *style = NULL;

  +#ifdef WITH_SELINUX

  +	char *role = NULL;

  +#endif

-  	int authenticated = 0;

+  	int r, authenticated = 0;

   	double tstart = monotime_double();

   

  @@ -268,6 +271,11 @@ input_userauth_request(int type, u_int32
@@ -37,9 +37,9 @@ 

  +			mm_inform_authrole(role);

  +#endif

  +		}

-  		userauth_banner();

+  		userauth_banner(ssh);

   		if (auth2_setup_methods_lists(authctxt) != 0)

-  			packet_disconnect("no authentication methods enabled");

+  			ssh_packet_disconnect(ssh,

  diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c

  --- openssh/auth2-gss.c.role-mls	2018-08-20 07:57:29.000000000 +0200

  +++ openssh/auth2-gss.c	2018-08-22 11:15:42.459799171 +0200
@@ -57,7 +57,7 @@ 

   	mic.length = len;

  -	ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,

  +#ifdef WITH_SELINUX

- +	if (authctxt->role && (strlen(authctxt->role) > 0))

+ +	if (authctxt->role && authctxt->role[0] != 0)

  +		xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role);

  +	else

  +#endif
@@ -197,15 +197,15 @@ 

  --- openssh/monitor.c.role-mls	2018-08-20 07:57:29.000000000 +0200

  +++ openssh/monitor.c	2018-08-22 11:19:56.006844867 +0200

  @@ -115,6 +115,9 @@ int mm_answer_sign(int, struct sshbuf *)

-  int mm_answer_pwnamallow(int, struct sshbuf *);

-  int mm_answer_auth2_read_banner(int, struct sshbuf *);

-  int mm_answer_authserv(int, struct sshbuf *);

+  int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);

+  int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);

+  int mm_answer_authserv(struct ssh *, int, struct sshbuf *);

  +#ifdef WITH_SELINUX

- +int mm_answer_authrole(int, struct sshbuf *);

+ +int mm_answer_authrole(struct ssh *, int, struct sshbuf *);

  +#endif

-  int mm_answer_authpassword(int, struct sshbuf *);

-  int mm_answer_bsdauthquery(int, struct sshbuf *);

-  int mm_answer_bsdauthrespond(int, struct sshbuf *);

+  int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);

+  int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);

+  int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);

  @@ -189,6 +192,9 @@ struct mon_table mon_dispatch_proto20[]

       {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},

       {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
@@ -227,12 +227,12 @@ 

   

   #ifdef USE_PAM

  @@ -842,6 +851,26 @@ mm_answer_authserv(int sock, struct sshb

-  	return (0);

+  	return found;

   }

   

  +#ifdef WITH_SELINUX

  +int

- +mm_answer_authrole(int sock, struct sshbuf *m)

+ +mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m)

  +{

  +	int r;

  +	monitor_permit_authentications(1);
@@ -251,7 +251,7 @@ 

  +#endif

  +

   int

-  mm_answer_authpassword(int sock, struct sshbuf *m)

+  mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m)

   {

  @@ -1218,7 +1247,7 @@ monitor_valid_userblob(u_char *data, u_i

   {
@@ -338,13 +338,13 @@ 

  --- openssh/monitor_wrap.h.role-mls	2018-08-22 11:14:56.818430941 +0200

  +++ openssh/monitor_wrap.h	2018-08-22 11:22:10.439929513 +0200

  @@ -44,6 +44,9 @@ DH *mm_choose_dh(int, int, int);

-  int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t,

-      const char *, u_int compat);

+  int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *,

+      const u_char *, size_t, const char *, u_int compat);

   void mm_inform_authserv(char *, char *);

  +#ifdef WITH_SELINUX

  +void mm_inform_authrole(char *);

  +#endif

-  struct passwd *mm_getpwnamallow(const char *);

+  struct passwd *mm_getpwnamallow(struct ssh *, const char *);

   char *mm_auth2_read_banner(void);

   int mm_auth_password(struct ssh *, char *);

  diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Makefile.in

@@ -1,28 +0,0 @@ 

- From 6010c0303a422a9c5fa8860c061bf7105eb7f8b2 Mon Sep 17 00:00:00 2001

- From: "djm@openbsd.org" <djm@openbsd.org>

- Date: Fri, 16 Nov 2018 03:03:10 +0000

- Subject: [PATCH] upstream: disallow empty incoming filename or ones that refer

-  to the

- 

- current directory; based on report/patch from Harry Sintonen

- 

- OpenBSD-Commit-ID: f27651b30eaee2df49540ab68d030865c04f6de9

- ---

-  scp.c | 5 +++--

-  1 file changed, 3 insertions(+), 2 deletions(-)

- 

- diff --git a/scp.c b/scp.c

- index 60682c687..4f3fdcd3d 100644

- --- a/scp.c

- +++ b/scp.c

- @@ -1106,7 +1106,8 @@ sink(int argc, char **argv)

-  			SCREWUP("size out of range");

-  		size = (off_t)ull;

-  

- -		if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {

- +		if (*cp == '\0' || strchr(cp, '/') != NULL ||

- +		    strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {

-  			run_err("error: unexpected filename: %s", cp);

-  			exit(1);

-  		}

- 

@@ -1,186 +0,0 @@ 

- From 631165f6c43d230df9174423aeb19fcf09a67ef4 Mon Sep 17 00:00:00 2001

- From: Damien Miller <djm@mindrot.org>

- Date: Mon, 22 Oct 2018 11:22:50 +1100

- Subject: [PATCH 1/7] fix compile for openssl 1.0.x w/ --with-ssl-engine

- 

- bz#2921, patch from cotequeiroz

- ---

-  openbsd-compat/openssl-compat.c | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c

- index 8b4a3627..590b66d1 100644

- --- a/openbsd-compat/openssl-compat.c

- +++ b/openbsd-compat/openssl-compat.c

- @@ -76,7 +76,7 @@ ssh_OpenSSL_add_all_algorithms(void)

-  	ENGINE_load_builtin_engines();

-  	ENGINE_register_all_complete();

-  

- -#if OPENSSL_VERSION_NUMBER < 0x10001000L

- +#if OPENSSL_VERSION_NUMBER < 0x10100000L

-  	OPENSSL_config(NULL);

-  #else

-  	OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |

- -- 

- 2.20.1

- 

- 

- From 55d7cdda4dc4e8284ccd276f73440be400250a1e Mon Sep 17 00:00:00 2001

- From: Darren Tucker <dtucker@dtucker.net>

- Date: Mon, 22 Oct 2018 20:05:18 +1100

- Subject: [PATCH 2/7] Include openssl compatibility.

- 

- Patch from rosenp at gmail.com via openssh-unix-dev.

- ---

-  ssh-keysign.c | 1 +

-  ssh_api.c     | 2 ++

-  2 files changed, 3 insertions(+)

- 

- diff --git a/ssh-keysign.c b/ssh-keysign.c

- index 744ecb4f..bcd1508c 100644

- --- a/ssh-keysign.c

- +++ b/ssh-keysign.c

- @@ -40,6 +40,7 @@

-  #include <openssl/evp.h>

-  #include <openssl/rand.h>

-  #include <openssl/rsa.h>

- +#include "openbsd-compat/openssl-compat.h"

-  #endif

-  

-  #include "xmalloc.h"

- diff --git a/ssh_api.c b/ssh_api.c

- index c84b4e71..e727c0d6 100644

- --- a/ssh_api.c

- +++ b/ssh_api.c

- @@ -29,6 +29,8 @@

-  #include "ssherr.h"

-  #include "sshbuf.h"

-  

- +#include "openbsd-compat/openssl-compat.h"

- +

-  #include <string.h>

-  

-  int	_ssh_exchange_banner(struct ssh *);

- -- 

- 2.20.1

- 

- 

- From 22092e375125dc602227afb8b2d3b285203e77c1 Mon Sep 17 00:00:00 2001

- From: Darren Tucker <dtucker@dtucker.net>

- Date: Mon, 5 Nov 2018 17:31:24 +1100

- Subject: [PATCH 3/7] Fix pasto for HAVE_EVP_CIPHER_CTX_SET_IV.

- 

- Prevents unnecessary redefinition.  Patch from mforney at mforney.org.

- ---

-  configure.ac | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/configure.ac b/configure.ac

- index 7379ab35..1041bf25 100644

- --- a/configure.ac

- +++ b/configure.ac

- @@ -2850,7 +2850,7 @@ if test "x$openssl" = "xyes" ; then

-  		[AC_DEFINE([HAVE_EVP_CIPHER_CTX_GET_IV], [1],

-  		    [Define if libcrypto has EVP_CIPHER_CTX_get_iv])])

-  	AC_SEARCH_LIBS([EVP_CIPHER_CTX_set_iv], [crypto],

- -		[AC_DEFINE([HAVE_EVP_CIPHER_CTX_GET_IV], [1],

- +		[AC_DEFINE([HAVE_EVP_CIPHER_CTX_SET_IV], [1],

-  		    [Define if libcrypto has EVP_CIPHER_CTX_set_iv])])

-  

-  	AC_SEARCH_LIBS([RSA_get0_crt_params], [crypto],

- -- 

- 2.20.1

- 

- 

- From 904d478f07deabb401f741f88c67ab2e07f742bd Mon Sep 17 00:00:00 2001

- From: Darren Tucker <dtucker@dtucker.net>

- Date: Sun, 11 Nov 2018 15:54:54 +1100

- Subject: [PATCH 4/7] Remove hardcoded service name in cygwin setup.

- 

- bz#2922, patch from Christian.Lupien at USherbrooke.ca, sanity check

- by vinschen at redhat.com.

- ---

-  contrib/cygwin/ssh-host-config | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/contrib/cygwin/ssh-host-config b/contrib/cygwin/ssh-host-config

- index 261020af..e9f038db 100644

- --- a/contrib/cygwin/ssh-host-config

- +++ b/contrib/cygwin/ssh-host-config

- @@ -307,7 +307,7 @@ check_service_files_ownership() {

-  

-    if [ -z "${run_service_as}" ]

-    then

- -    accnt_name=$(/usr/bin/cygrunsrv -VQ sshd |

- +    accnt_name=$(/usr/bin/cygrunsrv -VQ "${service_name}" |

-      		 /usr/bin/sed -ne 's/^Account *: *//gp')

-      if [ "${accnt_name}" = "LocalSystem" ]

-      then

- -- 

- 2.20.1

- 

- 

- From 4608a60cb4893a25490fd88ffdaaae6256381ae3 Mon Sep 17 00:00:00 2001

- From: Damien Miller <djm@mindrot.org>

- Date: Fri, 23 Nov 2018 10:45:20 +1100

- Subject: [PATCH 6/7] fix configure test for OpenSSL version

- 

- square brackets in case statements may be eaten by autoconf.

- 

- Report and fix from Filipp Gunbin; tweaked by naddy@

- ---

-  configure.ac | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/configure.ac b/configure.ac

- index 1041bf25..9920ede5 100644

- --- a/configure.ac

- +++ b/configure.ac

- @@ -2616,7 +2616,7 @@ if test "x$openssl" = "xyes" ; then

-  				AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")])

-  		                ;;

-  			100*)   ;; # 1.0.x

- -			101000[0123456]*)

- +			101000[[0123456]]*)

-  				# https://github.com/openssl/openssl/pull/4613

-  				AC_MSG_ERROR([OpenSSL 1.1.x versions prior to 1.1.0g have a bug that breaks their use with OpenSSH (have "$ssl_library_ver")])

-  				;;

- -- 

- 2.20.1

- 

- 

- From f429c1b2ef631f2855e51a790cf71761d752bbca Mon Sep 17 00:00:00 2001

- From: "djm@openbsd.org" <djm@openbsd.org>

- Date: Thu, 27 Dec 2018 23:02:11 +0000

- Subject: [PATCH 7/7] upstream: Request RSA-SHA2 signatures for

- 

- rsa-sha2-{256|512}-cert-v01@openssh.com cert algorithms; ok markus@

- 

- OpenBSD-Commit-ID: afc6f7ca216ccd821656d1c911d2a3deed685033

- ---

-  authfd.c | 8 +++++---

-  1 file changed, 5 insertions(+), 3 deletions(-)

- 

- diff --git a/authfd.c b/authfd.c

- index ecdd869a..62cbf8c1 100644

- --- a/authfd.c

- +++ b/authfd.c

- @@ -327,10 +327,12 @@ ssh_free_identitylist(struct ssh_identitylist *idl)

-  static u_int

-  agent_encode_alg(const struct sshkey *key, const char *alg)

-  {

- -	if (alg != NULL && key->type == KEY_RSA) {

- -		if (strcmp(alg, "rsa-sha2-256") == 0)

- +	if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) {

- +		if (strcmp(alg, "rsa-sha2-256") == 0 ||

- +		    strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)

-  			return SSH_AGENT_RSA_SHA2_256;

- -		else if (strcmp(alg, "rsa-sha2-512") == 0)

- +		if (strcmp(alg, "rsa-sha2-512") == 0 ||

- +		    strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)

-  			return SSH_AGENT_RSA_SHA2_512;

-  	}

-  	return 0;

- -- 

- 2.20.1

- 

@@ -1,62 +0,0 @@ 

- diff --git a/monitor.c b/monitor.c

- index 12b33e7..a1c3c97 100644

- --- a/monitor.c

- +++ b/monitor.c

- @@ -875,6 +875,34 @@ mm_answer_bsdauthrespond(int sock, struct sshbuf *m)

-  }

-  #endif

-  

- +/*

- + * Check that the key type appears in the supplied pattern list, ignoring

- + * mismastches in the signature algorithm. (Signature algorithm checks are

- + * performed in the unprivileged authentication code).

- + * Returns 1 on success, 0 otherwise.

- + */

- +static int

- +key_base_type_match(const struct sshkey *key, const char *list)

- +{

- +	char *s, *l, *ol = xstrdup(list);

- +	int found = 0;

- +

- +	l = ol;

- +	for ((s = strsep(&l, ",")); s && *s != '\0'; (s = strsep(&l, ","))) {

- +		if (sshkey_type_from_name(s) == key->type) {

- +			found = 1;

- +			break;

- +		}

- +	}

- +	if (!found) {

- +		debug("key type %s does not appear in list %s",

- +		    sshkey_ssh_name(key), list);

- +	}

- +

- +	free(ol);

- +	return found;

- +}

- +

-  int

-  mm_answer_keyallowed(int sock, struct sshbuf *m)

-  {

- @@ -909,8 +937,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m)

-  				break;

-  			if (auth2_key_already_used(authctxt, key))

-  				break;

- -			if (match_pattern_list(sshkey_ssh_name(key),

- -			    options.pubkey_key_types, 0) != 1)

- +			if (!key_base_type_match(key,

- +			    options.pubkey_key_types))

-  				break;

-  			allowed = user_key_allowed(ssh, authctxt->pw, key,

-  			    pubkey_auth_attempt, &opts);

- @@ -921,8 +949,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m)

-  				break;

-  			if (auth2_key_already_used(authctxt, key))

-  				break;

- -			if (match_pattern_list(sshkey_ssh_name(key),

- -			    options.hostbased_key_types, 0) != 1)

- +			if (!key_base_type_match(key,

- +			    options.hostbased_key_types))

-  				break;

-  			allowed = hostbased_key_allowed(authctxt->pw,

-  			    cuser, chost, key);

- 

@@ -1,150 +0,0 @@ 

- From bc74944ce7a2eabd228d47051f277ce108914c96 Mon Sep 17 00:00:00 2001

- From: Jakub Jelen <jjelen@redhat.com>

- Date: Tue, 16 Oct 2018 16:44:40 +0200

- Subject: [PATCH] Unbreak authentication using gssapi-keyex (#1625366)

- 

- ---

-  auth2-gss.c    |  6 +++---

-  gss-serv.c     |  4 +++-

-  monitor.c      | 13 ++++++++++---

-  monitor_wrap.c |  4 +++-

-  monitor_wrap.h |  2 +-

-  ssh-gss.h      |  2 +-

-  6 files changed, 21 insertions(+), 10 deletions(-)

- 

- diff --git a/auth2-gss.c b/auth2-gss.c

- index 3f2ad21d..a61ac089 100644

- --- a/auth2-gss.c

- +++ b/auth2-gss.c

- @@ -84,7 +84,7 @@ userauth_gsskeyex(Authctxt *authctxt)

-  	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 

-  	    &gssbuf, &mic))))

-  		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,

- -		    authctxt->pw));

- +		    authctxt->pw, 1));

-  	

-  	sshbuf_free(b);

-  	free(mic.value);

- @@ -299,7 +299,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)

-  		fatal("%s: %s", __func__, ssh_err(r));

-  

-  	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,

- -	    authctxt->pw));

- +	    authctxt->pw, 1));

-  

-  	if ((!use_privsep || mm_is_monitor()) &&

-  	    (displayname = ssh_gssapi_displayname()) != NULL)

- @@ -347,7 +347,7 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)

-  

-  	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))

-  		authenticated = 

- -		    PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));

- +		    PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw, 0));

-  	else

-  		logit("GSSAPI MIC check failed");

-  

- diff --git a/gss-serv.c b/gss-serv.c

- index 786ac95c..87de2baa 100644

- --- a/gss-serv.c

- +++ b/gss-serv.c

- @@ -493,10 +493,12 @@ verify_authentication_indicators(Gssctxt *gssctxt)

-  

-  /* Privileged */

-  int

- -ssh_gssapi_userok(char *user, struct passwd *pw)

- +ssh_gssapi_userok(char *user, struct passwd *pw, int kex)

-  {

-  	OM_uint32 lmin;

-  

- +	(void) kex; /* used in privilege separation */

- +

-  	if (gssapi_client.exportedname.length == 0 ||

-  	    gssapi_client.exportedname.value == NULL) {

-  		debug("No suitable client data");

- diff --git a/monitor.c b/monitor.c

- index 9bbe8cc4..7b1903af 100644

- --- a/monitor.c

- +++ b/monitor.c

- @@ -1877,14 +1877,17 @@ mm_answer_gss_checkmic(int sock, struct sshbuf *m)

-  int

-  mm_answer_gss_userok(int sock, struct sshbuf *m)

-  {

- -	int r, authenticated;

- +	int r, authenticated, kex;

-  	const char *displayname;

-  

-  	if (!options.gss_authentication && !options.gss_keyex)

-  		fatal("%s: GSSAPI authentication not enabled", __func__);

-  

- +	if ((r = sshbuf_get_u32(m, &kex)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

- +

-  	authenticated = authctxt->valid &&

- -	    ssh_gssapi_userok(authctxt->user, authctxt->pw);

- +	    ssh_gssapi_userok(authctxt->user, authctxt->pw, kex);

-  

-  	sshbuf_reset(m);

-  	if ((r = sshbuf_put_u32(m, authenticated)) != 0)

- @@ -1893,7 +1896,11 @@ mm_answer_gss_userok(int sock, struct sshbuf *m)

-  	debug3("%s: sending result %d", __func__, authenticated);

-  	mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);

-  

- -	auth_method = "gssapi-with-mic";

- +	if (kex) {

- +		auth_method = "gssapi-keyex";

- +	} else {

- +		auth_method = "gssapi-with-mic";

- +	}

-  

-  	if ((displayname = ssh_gssapi_displayname()) != NULL)

-  		auth2_record_info(authctxt, "%s", displayname);

- diff --git a/monitor_wrap.c b/monitor_wrap.c

- index fb52a530..508d926d 100644

- --- a/monitor_wrap.c

- +++ b/monitor_wrap.c

- @@ -984,13 +984,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)

-  }

-  

-  int

- -mm_ssh_gssapi_userok(char *user, struct passwd *pw)

- +mm_ssh_gssapi_userok(char *user, struct passwd *pw, int kex)

-  {

-  	struct sshbuf *m;

-  	int r, authenticated = 0;

-  

-  	if ((m = sshbuf_new()) == NULL)

-  		fatal("%s: sshbuf_new failed", __func__);

- +	if ((r = sshbuf_put_u32(m, kex)) != 0)

- +		fatal("%s: buffer error: %s", __func__, ssh_err(r));

-  

-  	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);

-  	mm_request_receive_expect(pmonitor->m_recvfd,

- diff --git a/monitor_wrap.h b/monitor_wrap.h

- index 494760dd..5eba5ecc 100644

- --- a/monitor_wrap.h

- +++ b/monitor_wrap.h

- @@ -60,7 +60,7 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,

-  OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);

-  OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,

-     gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);

- -int mm_ssh_gssapi_userok(char *user, struct passwd *);

- +int mm_ssh_gssapi_userok(char *user, struct passwd *, int kex);

-  OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);

-  OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);

-  int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);

- diff --git a/ssh-gss.h b/ssh-gss.h

- index 39b6ce69..98262837 100644

- --- a/ssh-gss.h

- +++ b/ssh-gss.h

- @@ -162,7 +162,7 @@ gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);

-  int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 

-      const char *);

-  OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);

- -int ssh_gssapi_userok(char *name, struct passwd *);

- +int ssh_gssapi_userok(char *name, struct passwd *, int kex);

-  OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);

-  void ssh_gssapi_do_child(char ***, u_int *);

-  void ssh_gssapi_cleanup_creds(void);

- -- 

- 2.17.2

- 

@@ -1,11 +0,0 @@ 

- diff --git a/session.c b/session.c

- --- a/session.c

- +++ b/session.c

- @@ -1859,6 +1859,7 @@ do_child(Session *s, const char *command)

-  

-  	if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) {

-  		printf("This service allows sftp connections only.\n");

- +		logit("The session allows sftp connections only");

-  		fflush(NULL);

-  		exit(1);

-  	} else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {

@@ -1,306 +0,0 @@ 

- commit 9e34e0c59ab04514f9de9934a772283f7f372afe

- Author: djm@openbsd.org <djm@openbsd.org>

- Date:   Fri Nov 23 05:08:07 2018 +0000

- 

-     upstream: add a ssh_config "Match final" predicate

-     

-     Matches in same pass as "Match canonical" but doesn't require

-     hostname canonicalisation be enabled. bz#2906 ok markus

-     

-     OpenBSD-Commit-ID: fba1dfe9f6e0cabcd0e2b3be13f7a434199beffa

- 

- diff --git a/readconf.c b/readconf.c

- index 7850f2f5..7331ef5a 100644

- --- a/readconf.c

- +++ b/readconf.c

- @@ -133,10 +133,11 @@

-  

-  static int read_config_file_depth(const char *filename, struct passwd *pw,

-      const char *host, const char *original_host, Options *options,

- -    int flags, int *activep, int depth);

- +    int flags, int *activep, int *want_final_pass, int depth);

-  static int process_config_line_depth(Options *options, struct passwd *pw,

-      const char *host, const char *original_host, char *line,

- -    const char *filename, int linenum, int *activep, int flags, int depth);

- +    const char *filename, int linenum, int *activep, int flags,

- +    int *want_final_pass, int depth);

-  

-  /* Keyword tokens. */

-  

- @@ -539,8 +540,8 @@ execute_in_shell(const char *cmd)

-   */

-  static int

-  match_cfg_line(Options *options, char **condition, struct passwd *pw,

- -    const char *host_arg, const char *original_host, int post_canon,

- -    const char *filename, int linenum)

- +    const char *host_arg, const char *original_host, int final_pass,

- +    int *want_final_pass, const char *filename, int linenum)

-  {

-  	char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;

-  	const char *ruser;

- @@ -554,7 +555,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,

-  	 */

-  	port = options->port <= 0 ? default_ssh_port() : options->port;

-  	ruser = options->user == NULL ? pw->pw_name : options->user;

- -	if (post_canon) {

- +	if (final_pass) {

-  		host = xstrdup(options->hostname);

-  	} else if (options->hostname != NULL) {

-  		/* NB. Please keep in sync with ssh.c:main() */

- @@ -586,8 +587,16 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,

-  			goto out;

-  		}

-  		attributes++;

- -		if (strcasecmp(attrib, "canonical") == 0) {

- -			r = !!post_canon;  /* force bitmask member to boolean */

- +		if (strcasecmp(attrib, "canonical") == 0 ||

- +		    strcasecmp(attrib, "final") == 0) {

- +			/*

- +			 * If the config requests "Match final" then remember

- +			 * this so we can perform a second pass later.

- +			 */

- +			if (strcasecmp(attrib, "final") == 0 &&

- +			    want_final_pass != NULL)

- +				*want_final_pass = 1;

- +			r = !!final_pass;  /* force bitmask member to boolean */

-  			if (r == (negate ? 1 : 0))

-  				this_result = result = 0;

-  			debug3("%.200s line %d: %smatched '%s'",

- @@ -824,14 +833,14 @@ process_config_line(Options *options, struct passwd *pw, const char *host,

-      int linenum, int *activep, int flags)

-  {

-  	return process_config_line_depth(options, pw, host, original_host,

- -	    line, filename, linenum, activep, flags, 0);

- +	    line, filename, linenum, activep, flags, NULL, 0);

-  }

-  

-  #define WHITESPACE " \t\r\n"

-  static int

-  process_config_line_depth(Options *options, struct passwd *pw, const char *host,

-      const char *original_host, char *line, const char *filename,

- -    int linenum, int *activep, int flags, int depth)

- +    int linenum, int *activep, int flags, int *want_final_pass, int depth)

-  {

-  	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;

-  	char **cpptr, fwdarg[256];

- @@ -1339,7 +1348,8 @@ parse_keytypes:

-  			fatal("Host directive not supported as a command-line "

-  			    "option");

-  		value = match_cfg_line(options, &s, pw, host, original_host,

- -		    flags & SSHCONF_POSTCANON, filename, linenum);

- +		    flags & SSHCONF_FINAL, want_final_pass,

- +		    filename, linenum);

-  		if (value < 0)

-  			fatal("%.200s line %d: Bad Match condition", filename,

-  			    linenum);

- @@ -1548,7 +1558,7 @@ parse_keytypes:

-  				    pw, host, original_host, options,

-  				    flags | SSHCONF_CHECKPERM |

-  				    (oactive ? 0 : SSHCONF_NEVERMATCH),

- -				    activep, depth + 1);

- +				    activep, want_final_pass, depth + 1);

-  				if (r != 1 && errno != ENOENT) {

-  					fatal("Can't open user config file "

-  					    "%.100s: %.100s", gl.gl_pathv[i],

- @@ -1751,19 +1761,20 @@ parse_keytypes:

-   */

-  int

-  read_config_file(const char *filename, struct passwd *pw, const char *host,

- -    const char *original_host, Options *options, int flags)

- +    const char *original_host, Options *options, int flags,

- +    int *want_final_pass)

-  {

-  	int active = 1;

-  

-  	return read_config_file_depth(filename, pw, host, original_host,

- -	    options, flags, &active, 0);

- +	    options, flags, &active, want_final_pass, 0);

-  }

-  

-  #define READCONF_MAX_DEPTH	16

-  static int

-  read_config_file_depth(const char *filename, struct passwd *pw,

-      const char *host, const char *original_host, Options *options,

- -    int flags, int *activep, int depth)

- +    int flags, int *activep, int *want_final_pass, int depth)

-  {

-  	FILE *f;

-  	char *line = NULL;

- @@ -1798,7 +1809,8 @@ read_config_file_depth(const char *filename, struct passwd *pw,

-  		/* Update line number counter. */

-  		linenum++;

-  		if (process_config_line_depth(options, pw, host, original_host,

- -		    line, filename, linenum, activep, flags, depth) != 0)

- +		    line, filename, linenum, activep, flags, want_final_pass,

- +		    depth) != 0)

-  			bad_options++;

-  	}

-  	free(line);

- diff --git a/readconf.h b/readconf.h

- index fc7e3825..8e36bf32 100644

- --- a/readconf.h

- +++ b/readconf.h

- @@ -185,7 +185,7 @@ typedef struct {

-  

-  #define SSHCONF_CHECKPERM	1  /* check permissions on config file */

-  #define SSHCONF_USERCONF	2  /* user provided config file not system */

- -#define SSHCONF_POSTCANON	4  /* After hostname canonicalisation */

- +#define SSHCONF_FINAL		4  /* Final pass over config, after canon. */

-  #define SSHCONF_NEVERMATCH	8  /* Match/Host never matches; internal only */

-  

-  #define SSH_UPDATE_HOSTKEYS_NO	0

- @@ -203,7 +203,7 @@ void	 fill_default_options_for_canonicalization(Options *);

-  int	 process_config_line(Options *, struct passwd *, const char *,

-      const char *, char *, const char *, int, int *, int);

-  int	 read_config_file(const char *, struct passwd *, const char *,

- -    const char *, Options *, int);

- +    const char *, Options *, int, int *);

-  int	 parse_forward(struct Forward *, const char *, int, int);

-  int	 parse_jump(const char *, Options *, int);

-  int	 parse_ssh_uri(const char *, char **, char **, int *);

- diff --git a/ssh-keysign.c b/ssh-keysign.c

- index 8f487b8c..7ea5ad0e 100644

- --- a/ssh-keysign.c

- +++ b/ssh-keysign.c

- @@ -208,7 +208,8 @@ main(int argc, char **argv)

-  

-  	/* verify that ssh-keysign is enabled by the admin */

-  	initialize_options(&options);

- -	(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", &options, 0);

- +	(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "",

- +	    &options, 0, NULL);

-  	fill_default_options(&options);

-  	if (options.enable_ssh_keysign != 1)

-  		fatal("ssh-keysign not enabled in %s",

- diff --git a/ssh.c b/ssh.c

- index 1ac903d1..c6cb7847 100644

- --- a/ssh.c

- +++ b/ssh.c

- @@ -527,7 +527,8 @@ check_load(int r, const char *path, const char *message)

-   * file if the user specifies a config file on the command line.

-   */

-  static void

- -process_config_files(const char *host_name, struct passwd *pw, int post_canon)

- +process_config_files(const char *host_name, struct passwd *pw, int final_pass,

- +    int *want_final_pass)

-  {

-  	char buf[PATH_MAX];

-  	int r;

- @@ -535,7 +536,8 @@ process_config_files(const char *host_name, struct passwd *pw, int post_canon)

-  	if (config != NULL) {

-  		if (strcasecmp(config, "none") != 0 &&

-  		    !read_config_file(config, pw, host, host_name, &options,

- -		    SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0)))

- +		    SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0),

- +		    want_final_pass))

-  			fatal("Can't open user config file %.100s: "

-  			    "%.100s", config, strerror(errno));

-  	} else {

- @@ -544,12 +546,12 @@ process_config_files(const char *host_name, struct passwd *pw, int post_canon)

-  		if (r > 0 && (size_t)r < sizeof(buf))

-  			(void)read_config_file(buf, pw, host, host_name,

-  			    &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |

- -			    (post_canon ? SSHCONF_POSTCANON : 0));

- +			    (final_pass ? SSHCONF_FINAL : 0), want_final_pass);

-  

-  		/* Read systemwide configuration file after user config. */

-  		(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,

-  		    host, host_name, &options,

- -		    post_canon ? SSHCONF_POSTCANON : 0);

- +		    final_pass ? SSHCONF_FINAL : 0, want_final_pass);

-  	}

-  }

-  

- @@ -581,7 +583,7 @@ main(int ac, char **av)

-  {

-  	struct ssh *ssh = NULL;

-  	int i, r, opt, exit_status, use_syslog, direct, timeout_ms;

- -	int was_addr, config_test = 0, opt_terminated = 0;

- +	int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;

-  	char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;

-  	char cname[NI_MAXHOST];

-  	struct stat st;

- @@ -1089,7 +1091,9 @@ main(int ac, char **av)

-  		);

-  

-  	/* Parse the configuration files */

- -	process_config_files(host_arg, pw, 0);

- +	process_config_files(host_arg, pw, 0, &want_final_pass);

- +	if (want_final_pass)

- +		debug("configuration requests final Match pass");

-  

-  	/* Hostname canonicalisation needs a few options filled. */

-  	fill_default_options_for_canonicalization(&options);

- @@ -1146,12 +1150,17 @@ main(int ac, char **av)

-  	 * If canonicalisation is enabled then re-parse the configuration

-  	 * files as new stanzas may match.

-  	 */

- -	if (options.canonicalize_hostname != 0) {

- -		debug("Re-reading configuration after hostname "

- -		    "canonicalisation");

- +	if (options.canonicalize_hostname != 0 && !want_final_pass) {

- +		debug("hostname canonicalisation enabled, "

- +		    "will re-parse configuration");

- +		want_final_pass = 1;

- +	}

- +

- +	if (want_final_pass) {

- +		debug("re-parsing configuration");

-  		free(options.hostname);

-  		options.hostname = xstrdup(host);

- -		process_config_files(host_arg, pw, 1);

- +		process_config_files(host_arg, pw, 1, NULL);

-  		/*

-  		 * Address resolution happens early with canonicalisation

-  		 * enabled and the port number may have changed since, so

- diff --git a/ssh_config.5 b/ssh_config.5

- index 4d5b01d3..58a5fa1c 100644

- --- a/ssh_config.5

- +++ b/ssh_config.5

- @@ -139,6 +139,7 @@ or the single token

-  which always matches.

-  The available criteria keywords are:

-  .Cm canonical ,

- +.Cm final ,

-  .Cm exec ,

-  .Cm host ,

-  .Cm originalhost ,

- @@ -148,12 +149,15 @@ and

-  The

-  .Cm all

-  criteria must appear alone or immediately after

- -.Cm canonical .

- +.Cm canonical

- +or

- +.Cm final .

-  Other criteria may be combined arbitrarily.

-  All criteria but

-  .Cm all

- -and

-  .Cm canonical

- +and

- +.Cm final

-  require an argument.

-  Criteria may be negated by prepending an exclamation mark

-  .Pq Sq !\& .

- @@ -166,6 +170,20 @@ after hostname canonicalization (see the

-  option.)

-  This may be useful to specify conditions that work with canonical host

-  names only.

- +.Pp

- +The

- +.Cm final

- +keyword requests that the configuration be re-parsed (regardless of whether

- +.Cm CanonicalizeHostname

- +is enabled), and matches only during this final pass.

- +If

- +.Cm CanonicalizeHostname

- +is enabled, then

- +.Cm canonical

- +and

- +.Cm final

- +match during the same pass.

- +.Pp

-  The

-  .Cm exec

-  keyword executes the specified command under the user's shell.

@@ -2,8 +2,8 @@ 

  --- openssh-7.4p1/session.c.update-pw	2019-03-04 14:10:57.287054645 +0100

  +++ openssh-7.4p1/session.c	2019-03-04 14:12:39.259997218 +0100

  @@ -1522,9 +1522,18 @@ do_child(Session *s, const char *command

-  	char **env;

-  	char *argv[ARGV_MAX];

+  	extern char **environ;

+  	char **env, *argv[ARGV_MAX], remote_id[512];

   	const char *shell, *shell0;

  -	struct passwd *pw = s->pw;

  +	struct passwd *pw = NULL;
@@ -18,6 +18,6 @@ 

  +		pw = s->pw;

  +	}

  +

+  	sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));

+  

   	/* remove hostkey from the child's memory */

-  	destroy_sensitive_data();

-  	packet_clear_keys();

The added file is too large to be shown here, see it at: openssh-8.0p1-gssapi-keyex.patch
The added file is too large to be shown here, see it at: openssh-8.0p1-pkcs11-uri.patch
file modified
+14 -51
@@ -65,10 +65,10 @@ 

  %endif

  

  # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1

- %global openssh_ver 7.9p1

- %global openssh_rel 5

+ %global openssh_ver 8.0p1

+ %global openssh_rel 1

  %global pam_ssh_agent_ver 0.10.3

- %global pam_ssh_agent_rel 6

+ %global pam_ssh_agent_rel 7

  

  Summary: An open source implementation of SSH protocol version 2

  Name: openssh
@@ -150,8 +150,6 @@ 

  Patch703: openssh-4.3p2-askpass-grab-info.patch

  #https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX)

  Patch707: openssh-7.7p1-redhat.patch

- #https://bugzilla.mindrot.org/show_bug.cgi?id=1640 (WONTFIX)

- Patch709: openssh-6.2p1-vendor.patch

  # warn users for unsupported UsePAM=no (#757545)

  Patch711: openssh-7.8p1-UsePAM-warning.patch

  # make aes-ctr ciphers use EVP engines such as AES-NI from OpenSSL
@@ -161,29 +159,21 @@ 

  # add SSH KDF CAVS test driver

  Patch714: openssh-6.7p1-kdf-cavs.patch

  

- 

- #http://www.sxw.org.uk/computing/patches/openssh.html

- #changed cache storage type - #848228

- Patch800: openssh-7.8p1-gsskex.patch

+ # GSSAPI Key Exchange (RFC 4462 + draft-ietf-curdle-gss-keyex-sha2-08)

+ # from https://github.com/openssh-gsskex/openssh-gsskex/tree/fedora/master

+ Patch800: openssh-8.0p1-gssapi-keyex.patch

  #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html

  Patch801: openssh-6.6p1-force_krb.patch

  # add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843)

  # CVE-2014-9278

  Patch802: openssh-6.6p1-GSSAPIEnablek5users.patch

- # Documentation about GSSAPI

- # from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=765655

- Patch803: openssh-7.1p1-gssapi-documentation.patch

  # Improve ccache handling in openssh (#991186, #1199363, #1566494)

  # https://bugzilla.mindrot.org/show_bug.cgi?id=2775

  Patch804: openssh-7.7p1-gssapi-new-unique.patch

  # Respect k5login_directory option in krk5.conf (#1328243)

  Patch805: openssh-7.2p2-k5login_directory.patch

- # Support SHA2 in GSS key exchanges from draft-ssorce-gss-keyex-sha2-02

- Patch807: openssh-7.5p1-gssapi-kex-with-ec.patch

- # Do not break when using AuthenticationMethods with gssapi-keyex auth method (#1625366)

- Patch808: openssh-7.9p1-gsskex-method.patch

  

- Patch900: openssh-6.1p1-gssapi-canohost.patch

+ 

  #https://bugzilla.mindrot.org/show_bug.cgi?id=1780

  Patch901: openssh-6.6p1-kuserok.patch

  # Use tty allocation for a remote scp (#985650)
@@ -194,16 +184,12 @@ 

  Patch918: openssh-6.6.1p1-log-in-chroot.patch

  # scp file into non-existing directory (#1142223)

  Patch919: openssh-6.6.1p1-scp-non-existing-directory.patch

- # Config parser shouldn't accept ip/port syntax (#1130733)

- Patch920: openssh-7.8p1-ip-port-config-parser.patch

  # apply upstream patch and make sshd -T more consistent (#1187521)

  Patch922: openssh-6.8p1-sshdT-output.patch

  # Add sftp option to force mode of created files (#1191055)

  Patch926: openssh-6.7p1-sftp-force-permission.patch

  # Restore compatible default (#89216)

  Patch929: openssh-6.9p1-permit-root-login.patch

- # Add GSSAPIKexAlgorithms option for server and client application

- Patch932: openssh-7.0p1-gssKexAlgorithms.patch

  # make s390 use /dev/ crypto devices -- ignore closefrom

  Patch939: openssh-7.2p2-s390-closefrom.patch

  # Move MAX_DISPLAYS to a configuration option (#1341302)
@@ -215,28 +201,13 @@ 

  # Sandbox adjustments for s390 and audit

  Patch950: openssh-7.5p1-sandbox.patch

  # PKCS#11 URIs (upstream #2817, 2nd iteration)

- Patch951: openssh-7.6p1-pkcs11-uri.patch

- # PKCS#11 ECDSA keys (upstream #2474, 8th iteration)

- Patch952: openssh-7.6p1-pkcs11-ecdsa.patch

+ Patch951: openssh-8.0p1-pkcs11-uri.patch

  # Unbreak scp between two IPv6 hosts (#1620333)

  Patch953: openssh-7.8p1-scp-ipv6.patch

- # Allow to disable RSA signatures with SHA-1 in server

- # https://bugzilla.mindrot.org/show_bug.cgi?id=2746

- Patch954: openssh-7.9p1-disable-sha1.patch

- # Backport Match final so the crypto-policies do not break canonicalization (#1630166)

- # https://bugzilla.mindrot.org/show_bug.cgi?id=2906

- Patch955: openssh-7.9p1-match-final.patch

- # Backport more after-release fixes (#1665611)

- Patch956: openssh-7.9p1-backports.patch

- # Backport patch for CVE-2018-20685 (#1665786)

- Patch957: openssh-7.9p1-CVE-2018-20685.patch

  # ssh-copy-id is unmaintained: Aggreagete patches

  #  - do not return 0 if the write fails (full disk)

  #  - shellcheck reports (upstream #2902)

  Patch958: openssh-7.9p1-ssh-copy-id.patch

- # log when a client requests an interactive session and only sftp is allowed

- # https://bugzilla.mindrot.org/show_bug.cgi?id=2960

- Patch959: openssh-7.9p1-log-sftp-only-connections.patch

  # Update cached passwd structure after PAM authentication (#1674541)

  Patch960: openssh-7.9p1-updated-cached-pw.patch

  
@@ -416,7 +387,6 @@ 

  %patch702 -p1 -b .progress

  %patch703 -p1 -b .grab-info

  %patch707 -p1 -b .redhat

- %patch709 -p1 -b .vendor

  %patch711 -p1 -b .log-usepam-no

  %patch712 -p1 -b .evp-ctr

  %patch713 -p1 -b .ctr-cavs
@@ -424,38 +394,26 @@ 

  # 

  %patch800 -p1 -b .gsskex

  %patch801 -p1 -b .force_krb

- %patch803 -p1 -b .gss-docs

  %patch804 -p1 -b .ccache_name

  %patch805 -p1 -b .k5login

  # 

- %patch900 -p1 -b .canohost

  %patch901 -p1 -b .kuserok

  %patch906 -p1 -b .fromto-remote

  %patch916 -p1 -b .contexts

  %patch918 -p1 -b .log-in-chroot

  %patch919 -p1 -b .scp

- %patch920 -p1 -b .config

  %patch802 -p1 -b .GSSAPIEnablek5users

  %patch922 -p1 -b .sshdt

  %patch926 -p1 -b .sftp-force-mode

  %patch929 -p1 -b .root-login

- %patch932 -p1 -b .gsskexalg

  %patch939 -p1 -b .s390-dev

  %patch944 -p1 -b .x11max

  %patch948 -p1 -b .systemd

- %patch807 -p1 -b .gsskex-ec

  %patch949 -p1 -b .refactor

  %patch950 -p1 -b .sandbox

  %patch951 -p1 -b .pkcs11-uri

- %patch952 -p1 -b .pkcs11-ecdsa

  %patch953 -p1 -b .scp-ipv6

- %patch808 -p1 -b .gsskex-method

- %patch954 -p1 -b .disable-sha1

- %patch955 -p1 -b .match-final

- %patch956 -p1 -b .backports

- %patch957 -p1 -b .CVE-2018-20685

  %patch958 -p1 -b .ssh-copy-id

- %patch959 -p1 -b .log-sftp-only

  %patch960 -p1 -b .update-pw

  

  %patch200 -p1 -b .audit
@@ -512,7 +470,6 @@ 

  	--with-default-path=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \

  	--with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \

  	--with-privsep-path=%{_var}/empty/sshd \

- 	--enable-vendor-patchlevel="FC-%{openssh_ver}-%{openssh_rel}" \

  	--disable-strip \

  	--without-zlib-version-check \

  	--with-ssl-engine \
@@ -760,6 +717,12 @@ 

  %endif

  

  %changelog

+ * Fri Apr 26 2019 Jakub Jelen <jjelen@redhat.com> - 8.0p1-1 + 0.10.3-7

+ - New upstream release

+ - Removed support for VendroPatchLevel configuration option

+ - Significant rework of GSSAPI Key Exchange

+ - Significant rework of PKCS#11 URI support

+ 

  * Mon Mar 11 2019 Jakub Jelen <jjelen@redhat.com> - 7.9p1-5 + 0.10.3.6

  - Fix kerberos cleanup procedures with GSSAPI

  - Update cached passwd structure after PAM authentication

file modified
+2 -2
@@ -1,4 +1,4 @@ 

- SHA512 (openssh-7.9p1.tar.gz) = 0412c9c429c9287f0794023951469c8e6ec833cdb55821bfa0300dd90d0879ff60484f620cffd93372641ab69bf0b032c2d700ccc680950892725fb631b7708e

- SHA512 (openssh-7.9p1.tar.gz.asc) = 881db1b541813136fabd9adb9f5430c4f0fae372c06c99cb049feb8526a573275fe80c129c89511dd4e65f73f41e29364fefaaf8b7c78835224691c488d5da32

+ SHA512 (openssh-8.0p1.tar.gz) = e280fa2d56f550efd37c5d2477670326261aa8b94d991f9eb17aad90e0c6c9c939efa90fe87d33260d0f709485cb05c379f0fd1bd44fc0d5190298b6398c9982

+ SHA512 (openssh-8.0p1.tar.gz.asc) = fe9e7383d9467e869762864f2b719165d9a3f2c5316c07067df1d45fc7819bd2cb8ef758454865595688804a4c160dd3d3aaee4c5f887859555d2c7bb8c4592b

  SHA512 (DJM-GPG-KEY.gpg) = db1191ed9b6495999e05eed2ef863fb5179bdb63e94850f192dad68eed8579836f88fbcfffd9f28524fe1457aff8cd248ee3e0afc112c8f609b99a34b80ecc0d

  SHA512 (pam_ssh_agent_auth-0.10.3.tar.bz2) = d75062c4e46b0b011f46aed9704a99049995fea8b5115ff7ee26dad7e93cbcf54a8af7efc6b521109d77dc03c6f5284574d2e1b84c6829cec25610f24fb4bd66

no initial comment

rebased onto 0f315f9

5 years ago

Pull-Request has been closed by jjelen

5 years ago
Changes Summary 35
+2 -0
file changed
.gitignore
-21
file removed
openssh-6.1p1-gssapi-canohost.patch
-142
file removed
openssh-6.2p1-vendor.patch
+2 -2
file changed
openssh-6.6.1p1-log-in-chroot.patch
+8 -6
file changed
openssh-6.6p1-GSSAPIEnablek5users.patch
+4 -4
file changed
openssh-6.6p1-kuserok.patch
+8 -8
file changed
openssh-6.7p1-coverity.patch
+13 -3
file changed
openssh-6.7p1-kdf-cavs.patch
+0 -15
file changed
openssh-6.8p1-sshdT-output.patch
-431
file removed
openssh-7.0p1-gssKexAlgorithms.patch
-52
file removed
openssh-7.1p1-gssapi-documentation.patch
+16 -16
file changed
openssh-7.1p2-audit-race-condition.patch
+6 -7
file changed
openssh-7.2p2-k5login_directory.patch
-1377
file removed
openssh-7.5p1-gssapi-kex-with-ec.patch
+533 -393
file changed
openssh-7.6p1-audit.patch
+50 -32
file changed
openssh-7.6p1-cleanup-selinux.patch
-794
file removed
openssh-7.6p1-pkcs11-ecdsa.patch
-4760
file removed
openssh-7.6p1-pkcs11-uri.patch
+77 -108
file changed
openssh-7.7p1-fips.patch
+8 -12
file changed
openssh-7.7p1-gssapi-new-unique.patch
+2 -2
file changed
openssh-7.8p1-UsePAM-warning.patch
-2905
file removed
openssh-7.8p1-gsskex.patch
-72
file removed
openssh-7.8p1-ip-port-config-parser.patch
+18 -18
file changed
openssh-7.8p1-role-mls.patch
-28
file removed
openssh-7.9p1-CVE-2018-20685.patch
-186
file removed
openssh-7.9p1-backports.patch
-62
file removed
openssh-7.9p1-disable-sha1.patch
-150
file removed
openssh-7.9p1-gsskex-method.patch
-11
file removed
openssh-7.9p1-log-sftp-only-connections.patch
-306
file removed
openssh-7.9p1-match-final.patch
+4 -4
file changed
openssh-7.9p1-updated-cached-pw.patch
+3924
file added
openssh-8.0p1-gssapi-keyex.patch
+2723
file added
openssh-8.0p1-pkcs11-uri.patch
+14 -51
file changed
openssh.spec
+2 -2
file changed
sources