View | Details | Raw Unified | Return to bug 2675 | Differences between
and this patch

Collapse All | Expand All

(-)a/ssh-add.c (-45 / +74 lines)
Lines 180-190 delete_all(int agent_fd) Link Here
180
static int
180
static int
181
add_file(int agent_fd, const char *filename, int key_only)
181
add_file(int agent_fd, const char *filename, int key_only)
182
{
182
{
183
	struct sshkey *private, *cert;
183
	struct sshkey *private, *cert = NULL;
184
	char *comment = NULL;
184
	char *comment = NULL;
185
	char msg[1024], *certpath = NULL;
185
	char msg[1024], *certpath = NULL;
186
	int r, fd, ret = -1;
186
	int r, fd, ret = -1;
187
	struct sshbuf *keyblob;
187
	struct sshbuf *keyblob;
188
	time_t now, ttl;
188
189
189
	if (strcmp(filename, "-") == 0) {
190
	if (strcmp(filename, "-") == 0) {
190
		fd = STDIN_FILENO;
191
		fd = STDIN_FILENO;
Lines 262-267 add_file(int agent_fd, const char *filename, int key_only) Link Here
262
		comment = xstrdup(filename);
263
		comment = xstrdup(filename);
263
	sshbuf_free(keyblob);
264
	sshbuf_free(keyblob);
264
265
266
	/*
267
	 * Before adding, check if a certificate exists. If it does, we'll use that to
268
	 * get an upper bound on an expiry time.
269
	 */
270
271
	/* Skip trying to load the cert if requested */
272
	if (!key_only) {
273
		/* Now try to add the certificate flavour too */
274
		xasprintf(&certpath, "%s-cert.pub", filename);
275
		if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) {
276
			if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
277
				error("Failed to load certificate \"%s\": %s",
278
				    certpath, ssh_err(r));
279
		}
280
	}
281
282
	/* If we do have a cert, check it matches the key and checkout against our lifetime param */
283
	if (cert != NULL) {
284
		if (!sshkey_equal_public(cert, private)) {
285
			error("Certificate %s does not match private key %s",
286
			    certpath, filename);
287
			goto out;
288
		}
289
290
		now = time(NULL);
291
		if ((int)cert->cert->valid_after > now)
292
			fprintf(stderr, "Warning: Certificate %s is not ready for use yet. Valid after: %lld. Adding anyway...\n",
293
			    certpath, cert->cert->valid_after);
294
295
		ttl = cert->cert->valid_before - now;
296
		if (ttl <= 0) {
297
			error("Certificate %s has expired. Valid before: %lld.",
298
			    certpath, cert->cert->valid_before);
299
			goto out;
300
		}
301
302
		if (lifetime == 0) {
303
			lifetime = ttl;
304
			fprintf(stderr, "Set lifetime to %d to match certificate expiry time.\n", lifetime);
305
		} else if (ttl < lifetime) {
306
			lifetime = ttl;
307
			fprintf(stderr, "Reducing lifetime to %d to match certificate expiry time.\n", lifetime);
308
		}
309
	}
310
311
	/* Now add the key */
265
	if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
312
	if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
266
	    lifetime, confirm)) == 0) {
313
	    lifetime, confirm)) == 0) {
267
		fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
314
		fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
Lines 274-331 add_file(int agent_fd, const char *filename, int key_only) Link Here
274
			    "The user must confirm each use of the key\n");
321
			    "The user must confirm each use of the key\n");
275
	} else {
322
	} else {
276
		fprintf(stderr, "Could not add identity \"%s\": %s\n",
323
		fprintf(stderr, "Could not add identity \"%s\": %s\n",
277
		    filename, ssh_err(r));
324
	            filename, ssh_err(r));
278
	}
279
280
	/* Skip trying to load the cert if requested */
281
	if (key_only)
282
		goto out;
283
284
	/* Now try to add the certificate flavour too */
285
	xasprintf(&certpath, "%s-cert.pub", filename);
286
	if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) {
287
		if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
288
			error("Failed to load certificate \"%s\": %s",
289
			    certpath, ssh_err(r));
290
		goto out;
291
	}
325
	}
292
326
293
	if (!sshkey_equal_public(cert, private)) {
327
	/* And finally add the cert */
294
		error("Certificate %s does not match private key %s",
328
	if (cert != NULL) {
295
		    certpath, filename);
329
		/* Graft with private bits */
296
		sshkey_free(cert);
330
		if ((r = sshkey_to_certified(private)) != 0) {
297
		goto out;
331
			error("%s: sshkey_to_certified: %s", __func__, ssh_err(r));
298
	} 
332
			goto out;
299
333
		}
300
	/* Graft with private bits */
334
		if ((r = sshkey_cert_copy(cert, private)) != 0) {
301
	if ((r = sshkey_to_certified(private)) != 0) {
335
			error("%s: key_cert_copy: %s", __func__, ssh_err(r));
302
		error("%s: sshkey_to_certified: %s", __func__, ssh_err(r));
336
			goto out;
303
		sshkey_free(cert);
337
		}
304
		goto out;
305
	}
306
	if ((r = sshkey_cert_copy(cert, private)) != 0) {
307
		error("%s: key_cert_copy: %s", __func__, ssh_err(r));
308
		sshkey_free(cert);
309
		goto out;
310
	}
311
	sshkey_free(cert);
312
338
313
	if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
339
		if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
314
	    lifetime, confirm)) != 0) {
340
		    lifetime, confirm)) != 0) {
315
		error("Certificate %s (%s) add failed: %s", certpath,
341
			error("Certificate %s (%s) add failed: %s", certpath,
316
		    private->cert->key_id, ssh_err(r));
342
			    private->cert->key_id, ssh_err(r));
317
		goto out;
343
			goto out;
344
		}
345
		fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
346
		    private->cert->key_id);
347
		if (lifetime != 0)
348
			fprintf(stderr, "Lifetime set to %d seconds\n", lifetime);
349
		if (confirm != 0)
350
			fprintf(stderr, "The user must confirm each use of the key\n");
318
	}
351
	}
319
	fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
320
	    private->cert->key_id);
321
	if (lifetime != 0)
322
		fprintf(stderr, "Lifetime set to %d seconds\n", lifetime);
323
	if (confirm != 0)
324
		fprintf(stderr, "The user must confirm each use of the key\n");
325
 out:
352
 out:
326
	free(certpath);
353
	free(certpath);
327
	free(comment);
354
	free(comment);
328
	sshkey_free(private);
355
	sshkey_free(private);
356
	if (cert != NULL)
357
		sshkey_free(cert);
329
358
330
	return ret;
359
	return ret;
331
}
360
}

Return to bug 2675