|
Lines 33-45
Link Here
|
| 33 |
#include <stdarg.h> |
33 |
#include <stdarg.h> |
| 34 |
#include <string.h> |
34 |
#include <string.h> |
| 35 |
#include <unistd.h> |
35 |
#include <unistd.h> |
|
|
36 |
#include <krb5.h> |
| 36 |
|
37 |
|
| 37 |
#include "openbsd-compat/sys-queue.h" |
38 |
#include "openbsd-compat/sys-queue.h" |
| 38 |
#include "xmalloc.h" |
39 |
#include "xmalloc.h" |
|
|
40 |
#include "ssh.h" |
| 39 |
#include "buffer.h" |
41 |
#include "buffer.h" |
|
|
42 |
#include "log.h" |
| 43 |
#include "misc.h" |
| 44 |
#include "servconf.h" |
| 40 |
#include "key.h" |
45 |
#include "key.h" |
| 41 |
#include "hostfile.h" |
46 |
#include "hostfile.h" |
| 42 |
#include "auth.h" |
47 |
#include "auth.h" |
|
|
48 |
#include "uidswap.h" |
| 49 |
#include "auth-options.h" |
| 43 |
#include "log.h" |
50 |
#include "log.h" |
| 44 |
#include "channels.h" |
51 |
#include "channels.h" |
| 45 |
#include "session.h" |
52 |
#include "session.h" |
|
Lines 47-52
Link Here
|
| 47 |
|
54 |
|
| 48 |
#include "ssh-gss.h" |
55 |
#include "ssh-gss.h" |
| 49 |
|
56 |
|
|
|
57 |
extern ServerOptions options; |
| 58 |
|
| 50 |
static ssh_gssapi_client gssapi_client = |
59 |
static ssh_gssapi_client gssapi_client = |
| 51 |
{ GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, |
60 |
{ GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, |
| 52 |
GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; |
61 |
GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; |
|
Lines 345-354
ssh_gssapi_do_child(char ***envp, u_int *envsizep)
Link Here
|
| 345 |
} |
354 |
} |
| 346 |
} |
355 |
} |
| 347 |
|
356 |
|
|
|
357 |
static int |
| 358 |
credential_read(krb5_context context, krb5_principal *princ, char **cpp) |
| 359 |
{ |
| 360 |
char *cp; |
| 361 |
char *name; |
| 362 |
size_t len; |
| 363 |
krb5_error_code retval; |
| 364 |
cp = *cpp; |
| 365 |
|
| 366 |
len = strcspn(cp, " \t\n#"); |
| 367 |
if (len == 0) |
| 368 |
return 0; |
| 369 |
name = strndup(cp, len); |
| 370 |
if (name == NULL) |
| 371 |
return 0; |
| 372 |
logit("%s(): cred \"%s\"", __func__, name); |
| 373 |
retval = krb5_parse_name_flags(context, name, |
| 374 |
KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, princ); |
| 375 |
if (retval) { |
| 376 |
debug("krb5_parse_name(\"%s\"): %.100s", |
| 377 |
name, krb5_get_err_text(context, retval)); |
| 378 |
free(name); |
| 379 |
return 0; |
| 380 |
} |
| 381 |
*cpp += len; |
| 382 |
|
| 383 |
free(name); |
| 384 |
return 1; |
| 385 |
} |
| 386 |
|
| 387 |
static int |
| 388 |
user_credential_allowed(Authctxt *authctxt, char *cred) |
| 389 |
{ |
| 390 |
char _line[SSH_MAX_PUBKEY_BYTES]; |
| 391 |
krb5_context context = NULL; |
| 392 |
krb5_principal sprinc = NULL, aprinc = NULL; |
| 393 |
krb5_error_code retval; |
| 394 |
char *file; |
| 395 |
FILE *f; |
| 396 |
struct passwd *pw = authctxt->pw; |
| 397 |
int found_credential = 0; |
| 398 |
u_long linenum = 0; |
| 399 |
char *line = NULL; |
| 400 |
const char *sp_name = NULL, *sp_inst = NULL, *sp_realm = NULL; |
| 401 |
|
| 402 |
/* Temporarily use the user's uid. */ |
| 403 |
temporarily_use_uid(pw); |
| 404 |
|
| 405 |
retval = krb5_init_context(&context); |
| 406 |
if (retval) { |
| 407 |
logit("%s: krb5_init_context(): %.100s", __func__, |
| 408 |
krb5_get_err_text(context, retval)); |
| 409 |
restore_uid(); |
| 410 |
return 0; |
| 411 |
} |
| 412 |
|
| 413 |
/* Session Principal */ |
| 414 |
retval = krb5_parse_name_flags(context, cred, |
| 415 |
KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &sprinc); |
| 416 |
if (retval) { |
| 417 |
logit("%s: krb5_parse_name(\"%s\"): %.100s", __func__, |
| 418 |
cred, krb5_get_err_text(context, retval)); |
| 419 |
krb5_free_context(context); |
| 420 |
restore_uid(); |
| 421 |
return 0; |
| 422 |
} |
| 423 |
|
| 424 |
#ifdef HAVE_KRB5_PRINCIPAL_GET |
| 425 |
sp_name = krb5_principal_get_comp_string(context, sprinc, 0); |
| 426 |
sp_inst = krb5_principal_get_comp_string(context, sprinc, 1); |
| 427 |
sp_realm = krb5_principal_get_realm(context, sprinc); |
| 428 |
#else |
| 429 |
krb5_data *tmp; |
| 430 |
|
| 431 |
tmp = krb5_princ_component(context, sprinc, 0); |
| 432 |
if (tmp) |
| 433 |
sp_name = tmp->data; |
| 434 |
tmp = krb5_princ_component(context, sprinc, 0); |
| 435 |
if (tmp) |
| 436 |
sp_inst = tmp->data; |
| 437 |
tmp = krb5_princ_realm(context, sprinc); |
| 438 |
if (tmp) |
| 439 |
sp_realm = tmp->data; |
| 440 |
#endif |
| 441 |
|
| 442 |
logit("%s: %s/%s@%s", __func__, sp_name, sp_inst, sp_realm); |
| 443 |
|
| 444 |
file = authorized_credentials_file(pw); |
| 445 |
debug("trying allowed credentials file %s", file); |
| 446 |
|
| 447 |
f = auth_opencredentialfile(file, pw, options.strict_modes); |
| 448 |
if (!f) { |
| 449 |
krb5_free_principal(context, sprinc); |
| 450 |
krb5_free_context(context); |
| 451 |
restore_uid(); |
| 452 |
return 0; |
| 453 |
} |
| 454 |
|
| 455 |
found_credential = 0; |
| 456 |
while (read_keyfile_line(f, file, _line, sizeof(_line), &linenum) != -1) { |
| 457 |
char *cp, *cred_options = NULL; |
| 458 |
int quoted = 0; |
| 459 |
int len = 0; |
| 460 |
|
| 461 |
if (line) |
| 462 |
free(line); |
| 463 |
line = percent_expand(_line, |
| 464 |
"c", cred, |
| 465 |
"h", pw->pw_dir, |
| 466 |
"u", pw->pw_name, |
| 467 |
"n", sp_name ? sp_name : "NONAME", |
| 468 |
"i", sp_inst ? sp_inst : "NOINST", |
| 469 |
"r", sp_realm ? sp_realm : "NOREALM", |
| 470 |
(char *)NULL); |
| 471 |
|
| 472 |
debug("original line: %s", _line); |
| 473 |
debug("expanded line: %s", line); |
| 474 |
|
| 475 |
auth_clear_options(); |
| 476 |
|
| 477 |
/* Skip leading whitespace, empty and comment lines. */ |
| 478 |
for (cp = line; *cp == ' ' || *cp == '\t'; cp++) |
| 479 |
; |
| 480 |
if (!*cp || *cp == '\n' || *cp == '#') |
| 481 |
continue; |
| 482 |
|
| 483 |
cred_options = cp; |
| 484 |
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { |
| 485 |
if (*cp == '\\' && cp[1] == '"') |
| 486 |
cp++; /* Skip both */ |
| 487 |
else if (*cp == '"') |
| 488 |
quoted = !quoted; |
| 489 |
} |
| 490 |
|
| 491 |
if (*cp == '\n' || *cp == '\0') { /* No options, rewind */ |
| 492 |
cp = cred_options; |
| 493 |
cred_options = NULL; |
| 494 |
} else { |
| 495 |
len = cp - cred_options; |
| 496 |
/* Skip remaining whitespace. */ |
| 497 |
for (; *cp == ' ' || *cp == '\t'; cp++) |
| 498 |
; |
| 499 |
} |
| 500 |
debug("%lu: cred: \"%s\"", linenum, cp); |
| 501 |
if (cred_options) |
| 502 |
debug("%lu: options: \"%.*s\"", |
| 503 |
linenum, len, cred_options); |
| 504 |
|
| 505 |
|
| 506 |
if (credential_read(context, &aprinc, &cp) != 1) { |
| 507 |
debug2("%s: advance: '%s'", __func__, cp); |
| 508 |
continue; |
| 509 |
} |
| 510 |
debug("%lu: options \"%.*s\"", linenum, len, cred_options); |
| 511 |
|
| 512 |
if (auth_parse_options(pw, cred_options, file, linenum) != 1) |
| 513 |
continue; |
| 514 |
|
| 515 |
if (krb5_principal_compare(context, sprinc, aprinc)) { |
| 516 |
found_credential = 1; |
| 517 |
debug("matching credential found: file %s, line %lu", |
| 518 |
file, linenum); |
| 519 |
break; |
| 520 |
} |
| 521 |
} |
| 522 |
if (sprinc) |
| 523 |
krb5_free_principal(context, sprinc); |
| 524 |
if (aprinc) |
| 525 |
krb5_free_principal(context, aprinc); |
| 526 |
if (context) |
| 527 |
krb5_free_context(context); |
| 528 |
restore_uid(); |
| 529 |
fclose(f); |
| 530 |
if (line) |
| 531 |
free(line); |
| 532 |
if (!found_credential) |
| 533 |
debug2("credential not found"); |
| 534 |
return found_credential; |
| 535 |
} |
| 536 |
|
| 348 |
/* Privileged */ |
537 |
/* Privileged */ |
| 349 |
int |
538 |
int |
| 350 |
ssh_gssapi_userok(char *user) |
539 |
ssh_gssapi_userok(Authctxt *authctxt) |
| 351 |
{ |
540 |
{ |
|
|
541 |
char *user = authctxt->user; |
| 352 |
OM_uint32 lmin; |
542 |
OM_uint32 lmin; |
| 353 |
|
543 |
|
| 354 |
if (gssapi_client.exportedname.length == 0 || |
544 |
if (gssapi_client.exportedname.length == 0 || |
|
Lines 357-363
ssh_gssapi_userok(char *user)
Link Here
|
| 357 |
return 0; |
547 |
return 0; |
| 358 |
} |
548 |
} |
| 359 |
if (gssapi_client.mech && gssapi_client.mech->userok) |
549 |
if (gssapi_client.mech && gssapi_client.mech->userok) |
| 360 |
if ((*gssapi_client.mech->userok)(&gssapi_client, user)) |
550 |
if (user_credential_allowed(authctxt, |
|
|
551 |
(char *)gssapi_client.displayname.value) || |
| 552 |
(*gssapi_client.mech->userok)(&gssapi_client, user)) |
| 361 |
return 1; |
553 |
return 1; |
| 362 |
else { |
554 |
else { |
| 363 |
/* Destroy delegated credentials if userok fails */ |
555 |
/* Destroy delegated credentials if userok fails */ |