|
Lines 109-117
typedef struct {
Link Here
|
| 109 |
u_int sockets_alloc = 0; |
109 |
u_int sockets_alloc = 0; |
| 110 |
SocketEntry *sockets = NULL; |
110 |
SocketEntry *sockets = NULL; |
| 111 |
|
111 |
|
|
|
112 |
typedef struct refcountkey { |
| 113 |
struct sshkey *key; |
| 114 |
int count; |
| 115 |
} RefcountKey; |
| 116 |
|
| 112 |
typedef struct identity { |
117 |
typedef struct identity { |
| 113 |
TAILQ_ENTRY(identity) next; |
118 |
TAILQ_ENTRY(identity) next; |
| 114 |
struct sshkey *key; |
119 |
RefcountKey *idkey; |
|
|
120 |
RefcountKey *shadowed_key; |
| 115 |
char *comment; |
121 |
char *comment; |
| 116 |
char *provider; |
122 |
char *provider; |
| 117 |
time_t death; |
123 |
time_t death; |
|
Lines 185-200
idtab_lookup(int version)
Link Here
|
| 185 |
return &idtable[version]; |
191 |
return &idtable[version]; |
| 186 |
} |
192 |
} |
| 187 |
|
193 |
|
|
|
194 |
static RefcountKey * |
| 195 |
refkey_new(struct sshkey *key) |
| 196 |
{ |
| 197 |
RefcountKey *ref = xcalloc(1, sizeof(RefcountKey)); |
| 198 |
|
| 199 |
ref->key = key; |
| 200 |
ref->count = 1; |
| 201 |
|
| 202 |
return ref; |
| 203 |
} |
| 204 |
|
| 205 |
static RefcountKey * |
| 206 |
refkey_addref(RefcountKey *refkey) |
| 207 |
{ |
| 208 |
++refkey->count; |
| 209 |
return refkey; |
| 210 |
} |
| 211 |
|
| 212 |
static void refkey_unref(RefcountKey *refkey) |
| 213 |
{ |
| 214 |
if (refkey && --refkey->count <= 0) { |
| 215 |
sshkey_free(refkey->key); |
| 216 |
free(refkey); |
| 217 |
} |
| 218 |
} |
| 219 |
|
| 188 |
static void |
220 |
static void |
| 189 |
free_identity(Identity *id) |
221 |
free_identity(Identity *id) |
| 190 |
{ |
222 |
{ |
| 191 |
sshkey_free(id->key); |
223 |
refkey_unref(id->idkey); |
|
|
224 |
refkey_unref(id->shadowed_key); |
| 192 |
free(id->provider); |
225 |
free(id->provider); |
| 193 |
free(id->comment); |
226 |
free(id->comment); |
| 194 |
free(id); |
227 |
free(id); |
| 195 |
} |
228 |
} |
| 196 |
|
229 |
|
| 197 |
/* return matching private key for given public key */ |
230 |
/* return matching Identity for given public key */ |
| 198 |
static Identity * |
231 |
static Identity * |
| 199 |
lookup_identity(struct sshkey *key, int version) |
232 |
lookup_identity(struct sshkey *key, int version) |
| 200 |
{ |
233 |
{ |
|
Lines 202-208
lookup_identity(struct sshkey *key, int version)
Link Here
|
| 202 |
|
235 |
|
| 203 |
Idtab *tab = idtab_lookup(version); |
236 |
Idtab *tab = idtab_lookup(version); |
| 204 |
TAILQ_FOREACH(id, &tab->idlist, next) { |
237 |
TAILQ_FOREACH(id, &tab->idlist, next) { |
| 205 |
if (sshkey_equal(key, id->key)) |
238 |
if (sshkey_equal(key, id->idkey->key)) |
|
|
239 |
return (id); |
| 240 |
} |
| 241 |
return (NULL); |
| 242 |
} |
| 243 |
|
| 244 |
/* return matching private key for given public key */ |
| 245 |
static Identity * |
| 246 |
lookup_identity_unshadowed_key(struct sshkey *key, int version) |
| 247 |
{ |
| 248 |
Identity *id; |
| 249 |
|
| 250 |
Idtab *tab = idtab_lookup(version); |
| 251 |
TAILQ_FOREACH(id, &tab->idlist, next) { |
| 252 |
if (sshkey_equal_public(key, id->idkey->key) && |
| 253 |
id->shadowed_key == NULL) |
| 206 |
return (id); |
254 |
return (id); |
| 207 |
} |
255 |
} |
| 208 |
return (NULL); |
256 |
return (NULL); |
|
Lines 215-221
confirm_key(Identity *id)
Link Here
|
| 215 |
char *p; |
263 |
char *p; |
| 216 |
int ret = -1; |
264 |
int ret = -1; |
| 217 |
|
265 |
|
| 218 |
p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT); |
266 |
p = sshkey_fingerprint(id->idkey->key, fingerprint_hash, SSH_FP_DEFAULT); |
| 219 |
if (p != NULL && |
267 |
if (p != NULL && |
| 220 |
ask_permission("Allow use of key %s?\nKey fingerprint %s.", |
268 |
ask_permission("Allow use of key %s?\nKey fingerprint %s.", |
| 221 |
id->comment, p)) |
269 |
id->comment, p)) |
|
Lines 253-266
process_request_identities(SocketEntry *e, int version)
Link Here
|
| 253 |
(r = sshbuf_put_u32(msg, tab->nentries)) != 0) |
301 |
(r = sshbuf_put_u32(msg, tab->nentries)) != 0) |
| 254 |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
302 |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
| 255 |
TAILQ_FOREACH(id, &tab->idlist, next) { |
303 |
TAILQ_FOREACH(id, &tab->idlist, next) { |
| 256 |
if (id->key->type == KEY_RSA1) { |
304 |
if (id->idkey->key->type == KEY_RSA1) { |
| 257 |
#ifdef WITH_SSH1 |
305 |
#ifdef WITH_SSH1 |
| 258 |
if ((r = sshbuf_put_u32(msg, |
306 |
if ((r = sshbuf_put_u32(msg, |
| 259 |
BN_num_bits(id->key->rsa->n))) != 0 || |
307 |
BN_num_bits(id->idkey->key->rsa->n))) != 0 || |
| 260 |
(r = sshbuf_put_bignum1(msg, |
308 |
(r = sshbuf_put_bignum1(msg, |
| 261 |
id->key->rsa->e)) != 0 || |
309 |
id->idkey->key->rsa->e)) != 0 || |
| 262 |
(r = sshbuf_put_bignum1(msg, |
310 |
(r = sshbuf_put_bignum1(msg, |
| 263 |
id->key->rsa->n)) != 0) |
311 |
id->idkey->key->rsa->n)) != 0) |
| 264 |
fatal("%s: buffer error: %s", |
312 |
fatal("%s: buffer error: %s", |
| 265 |
__func__, ssh_err(r)); |
313 |
__func__, ssh_err(r)); |
| 266 |
#endif |
314 |
#endif |
|
Lines 268-274
process_request_identities(SocketEntry *e, int version)
Link Here
|
| 268 |
u_char *blob; |
316 |
u_char *blob; |
| 269 |
size_t blen; |
317 |
size_t blen; |
| 270 |
|
318 |
|
| 271 |
if ((r = sshkey_to_blob(id->key, &blob, &blen)) != 0) { |
319 |
if ((r = sshkey_to_blob(id->idkey->key, &blob, &blen)) != 0) { |
| 272 |
error("%s: sshkey_to_blob: %s", __func__, |
320 |
error("%s: sshkey_to_blob: %s", __func__, |
| 273 |
ssh_err(r)); |
321 |
ssh_err(r)); |
| 274 |
continue; |
322 |
continue; |
|
Lines 324-330
process_authentication_challenge1(SocketEntry *e)
Link Here
|
| 324 |
|
372 |
|
| 325 |
id = lookup_identity(key, 1); |
373 |
id = lookup_identity(key, 1); |
| 326 |
if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { |
374 |
if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { |
| 327 |
struct sshkey *private = id->key; |
375 |
struct sshkey *private = id->idkey->key; |
| 328 |
/* Decrypt the challenge using the private key. */ |
376 |
/* Decrypt the challenge using the private key. */ |
| 329 |
if ((r = rsa_private_decrypt(challenge, challenge, |
377 |
if ((r = rsa_private_decrypt(challenge, challenge, |
| 330 |
private->rsa) != 0)) { |
378 |
private->rsa) != 0)) { |
|
Lines 377-383
process_sign_request2(SocketEntry *e)
Link Here
|
| 377 |
u_int compat = 0, flags; |
425 |
u_int compat = 0, flags; |
| 378 |
int r, ok = -1; |
426 |
int r, ok = -1; |
| 379 |
struct sshbuf *msg; |
427 |
struct sshbuf *msg; |
| 380 |
struct sshkey *key; |
428 |
struct sshkey *key, *sign_key; |
| 381 |
struct identity *id; |
429 |
struct identity *id; |
| 382 |
|
430 |
|
| 383 |
if ((msg = sshbuf_new()) == NULL) |
431 |
if ((msg = sshbuf_new()) == NULL) |
|
Lines 400-406
process_sign_request2(SocketEntry *e)
Link Here
|
| 400 |
verbose("%s: user refused key", __func__); |
448 |
verbose("%s: user refused key", __func__); |
| 401 |
goto send; |
449 |
goto send; |
| 402 |
} |
450 |
} |
| 403 |
if ((r = sshkey_sign(id->key, &signature, &slen, |
451 |
|
|
|
452 |
if (id->shadowed_key) |
| 453 |
sign_key = id->shadowed_key->key; |
| 454 |
else |
| 455 |
sign_key = id->idkey->key; |
| 456 |
if ((r = sshkey_sign(sign_key, &signature, &slen, |
| 404 |
data, dlen, compat)) != 0) { |
457 |
data, dlen, compat)) != 0) { |
| 405 |
error("%s: sshkey_sign: %s", __func__, ssh_err(ok)); |
458 |
error("%s: sshkey_sign: %s", __func__, ssh_err(ok)); |
| 406 |
goto send; |
459 |
goto send; |
|
Lines 640-651
process_add_identity(SocketEntry *e, int version)
Link Here
|
| 640 |
} |
693 |
} |
| 641 |
} |
694 |
} |
| 642 |
|
695 |
|
| 643 |
success = 1; |
|
|
| 644 |
if (lifetime && !death) |
696 |
if (lifetime && !death) |
| 645 |
death = monotime() + lifetime; |
697 |
death = monotime() + lifetime; |
|
|
698 |
|
| 699 |
/* handle additional certificates for an existing private key */ |
| 700 |
if (!sshkey_is_private(k)) { |
| 701 |
id = lookup_identity_unshadowed_key(k, version); |
| 702 |
/* ensure we have a private key and this cert is new */ |
| 703 |
if (id != NULL && lookup_identity(k, version) == NULL) { |
| 704 |
Identity *certid = xcalloc(1, sizeof(Identity)); |
| 705 |
certid->idkey = refkey_new(k); |
| 706 |
certid->shadowed_key = refkey_addref(id->idkey); |
| 707 |
if (id->provider) |
| 708 |
certid->provider = xstrdup(id->provider); |
| 709 |
if (id->comment) |
| 710 |
certid->comment = xstrdup(id->comment); /* XXX */ |
| 711 |
certid->death = death; |
| 712 |
certid->confirm = confirm | id->confirm; |
| 713 |
|
| 714 |
TAILQ_INSERT_TAIL(&tab->idlist, certid, next); |
| 715 |
tab->nentries++; |
| 716 |
success = 1; |
| 717 |
} else |
| 718 |
sshkey_free(k); |
| 719 |
|
| 720 |
free(comment); |
| 721 |
goto send; |
| 722 |
} |
| 723 |
|
| 724 |
success = 1; |
| 646 |
if ((id = lookup_identity(k, version)) == NULL) { |
725 |
if ((id = lookup_identity(k, version)) == NULL) { |
| 647 |
id = xcalloc(1, sizeof(Identity)); |
726 |
id = xcalloc(1, sizeof(Identity)); |
| 648 |
id->key = k; |
727 |
id->idkey = refkey_new(k); |
| 649 |
TAILQ_INSERT_TAIL(&tab->idlist, id, next); |
728 |
TAILQ_INSERT_TAIL(&tab->idlist, id, next); |
| 650 |
/* Increment the number of identities. */ |
729 |
/* Increment the number of identities. */ |
| 651 |
tab->nentries++; |
730 |
tab->nentries++; |
|
Lines 771-777
process_add_smartcard_key(SocketEntry *e)
Link Here
|
| 771 |
tab = idtab_lookup(version); |
850 |
tab = idtab_lookup(version); |
| 772 |
if (lookup_identity(k, version) == NULL) { |
851 |
if (lookup_identity(k, version) == NULL) { |
| 773 |
id = xcalloc(1, sizeof(Identity)); |
852 |
id = xcalloc(1, sizeof(Identity)); |
| 774 |
id->key = k; |
853 |
id->idkey = refkey_new(k); |
| 775 |
id->provider = xstrdup(provider); |
854 |
id->provider = xstrdup(provider); |
| 776 |
id->comment = xstrdup(provider); /* XXX */ |
855 |
id->comment = xstrdup(provider); /* XXX */ |
| 777 |
id->death = death; |
856 |
id->death = death; |
| 778 |
- |
|
|