|
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 |
} |