upstream commit

add ssh_config CertificateFile option to explicitly list
 a certificate; patch from Meghana Bhat on bz#2436; ok markus@

Upstream-ID: 58648ec53c510b41c1f46d8fe293aadc87229ab8
diff --git a/readconf.c b/readconf.c
index 354e292..09888b1 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.240 2015/08/21 23:53:08 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.241 2015/09/24 06:15:11 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -135,6 +135,7 @@
 	oPasswordAuthentication, oRSAAuthentication,
 	oChallengeResponseAuthentication, oXAuthLocation,
 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
+	oCertificateFile,
 	oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
@@ -202,6 +203,7 @@
 	{ "identityfile", oIdentityFile },
 	{ "identityfile2", oIdentityFile },			/* obsolete */
 	{ "identitiesonly", oIdentitiesOnly },
+	{ "certificatefile", oCertificateFile },
 	{ "hostname", oHostName },
 	{ "hostkeyalias", oHostKeyAlias },
 	{ "proxycommand", oProxyCommand },
@@ -366,6 +368,30 @@
 }
 
 void
+add_certificate_file(Options *options, const char *path, int userprovided)
+{
+	int i;
+
+	if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
+		fatal("Too many certificate files specified (max %d)",
+		    SSH_MAX_CERTIFICATE_FILES);
+
+	/* Avoid registering duplicates */
+	for (i = 0; i < options->num_certificate_files; i++) {
+		if (options->certificate_file_userprovided[i] == userprovided &&
+		    strcmp(options->certificate_files[i], path) == 0) {
+			debug2("%s: ignoring duplicate key %s", __func__, path);
+			return;
+		}
+	}
+
+	options->certificate_file_userprovided[options->num_certificate_files] =
+	    userprovided;
+	options->certificate_files[options->num_certificate_files++] =
+	    xstrdup(path);
+}
+
+void
 add_identity_file(Options *options, const char *dir, const char *filename,
     int userprovided)
 {
@@ -981,6 +1007,24 @@
 		}
 		break;
 
+	case oCertificateFile:
+		arg = strdelim(&s);
+		if (!arg || *arg == '\0')
+			fatal("%.200s line %d: Missing argument.",
+			    filename, linenum);
+		if (*activep) {
+			intptr = &options->num_certificate_files;
+			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
+				fatal("%.200s line %d: Too many certificate "
+				    "files specified (max %d).",
+				    filename, linenum,
+				    SSH_MAX_CERTIFICATE_FILES);
+			}
+			add_certificate_file(options, arg,
+			    flags & SSHCONF_USERCONF);
+		}
+		break;
+
 	case oXAuthLocation:
 		charptr=&options->xauth_location;
 		goto parse_string;
@@ -1625,6 +1669,7 @@
 	options->hostkeyalgorithms = NULL;
 	options->protocol = SSH_PROTO_UNKNOWN;
 	options->num_identity_files = 0;
+	options->num_certificate_files = 0;
 	options->hostname = NULL;
 	options->host_key_alias = NULL;
 	options->proxy_command = NULL;