2
* $Id: aklog_main.c,v 1.1.2.14 2006/08/29 19:19:05 shadow Exp $
2
* $Id: aklog_main.c,v 1.1.2.26 2008/04/01 18:15:53 shadow Exp $
4
4
* Copyright 1990,1991 by the Massachusetts Institute of Technology
5
5
* For distribution and copying rights, see the file "mit-copyright.h"
8
#if !defined(lint) && !defined(SABER)
10
"$Id: aklog_main.c,v 1.1.2.14 2006/08/29 19:19:05 shadow Exp $";
11
#endif /* lint || SABER */
8
* Copyright (c) 2005, 2006
9
* The Linux Box Corporation
12
* Permission is granted to use, copy, create derivative works
13
* and redistribute this software and such derivative works
14
* for any purpose, so long as the name of the Linux Box
15
* Corporation is not used in any advertising or publicity
16
* pertaining to the use or distribution of this software
17
* without specific, written prior authorization. If the
18
* above copyright notice or any other identification of the
19
* Linux Box Corporation is included in any copy of any
20
* portion of this software, then the disclaimer below must
23
* This software is provided as is, without representation
24
* from the Linux Box Corporation as to its fitness for any
25
* purpose, and without warranty by the Linux Box Corporation
26
* of any kind, either express or implied, including
27
* without limitation the implied warranties of
28
* merchantability and fitness for a particular purpose. The
29
* regents of the Linux Box Corporation shall not be liable
30
* for any damages, including special, indirect, incidental, or
31
* consequential damages, with respect to any claim arising
32
* out of or in connection with the use of the software, even
33
* if it has been or is hereafter advised of the possibility of
13
37
#include <afsconfig.h>
39
("$Header: /cvs/openafs/src/aklog/aklog_main.c,v 1.1.2.26 2008/04/01 18:15:53 shadow Exp $");
15
41
#include <string.h>
483
453
cell_to_use, ak_cellconfig.hostName[0]);
487
* Find out which realm we're supposed to authenticate to. If one
488
* is not included, use the kerberos realm found in the credentials
492
if (realm && realm[0]) {
493
strcpy(realm_of_cell, realm);
495
printf("We were told to authenticate to realm %s.\n", realm);
499
char *realm = afs_realm_of_cell(context, &ak_cellconfig);
503
"%s: Couldn't figure out realm for cell %s.\n",
504
progname, cell_to_use);
508
strcpy(realm_of_cell, realm);
511
printf("We've deduced that we need to authenticate to"
512
" realm %s.\n", realm_of_cell);
516
/* We use the afs.<cellname> convention here...
518
* Doug Engert's original code had principals of the form:
522
* in the KDC, so the name wouldn't conflict with DFS. Since we're
523
* not using DFS, I changed it just to look for the following
529
* Because people are transitioning from afs@realm to afs/cell,
530
* we configure things so that if the first one isn't found, we
531
* try the second one. You can select which one you prefer with
532
* a configure option.
535
strcpy(name, AFSKEY);
537
if (AFS_TRY_FULL_PRINC || strcasecmp(cell_to_use, realm_of_cell) != 0) {
538
strncpy(primary_instance, cell_to_use, sizeof(primary_instance));
539
primary_instance[sizeof(primary_instance)-1] = '\0';
540
if (strcasecmp(cell_to_use, realm_of_cell) == 0) {
542
secondary_instance[0] = '\0';
545
primary_instance[0] = '\0';
547
strncpy(secondary_instance, cell_to_use,
548
sizeof(secondary_instance));
549
secondary_instance[sizeof(secondary_instance)-1] = '\0';
553
* Extract the session key from the ticket file and hand-frob an
554
* afs style authenticator.
558
* Try to obtain AFS tickets. Because there are two valid service
559
* names, we will try both, but trying the more specific first.
561
* afs/<cell>@<realm> i.e. allow for single name with "."
566
printf("Getting tickets: %s/%s@%s\n", name,
567
primary_instance, realm_of_cell);
570
status = get_credv5(context, name, primary_instance, realm_of_cell,
573
if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || status == KRB5KRB_ERR_GENERIC) {
576
printf("Principal not found, trying alternate "
577
"service name: %s/%s@%s\n", name,
578
secondary_instance, realm_of_cell);
580
status = get_credv5(context, name, secondary_instance,
456
if ((status = get_user_realm(context, realm_of_user))) {
457
fprintf(stderr, "%s: Couldn't determine realm of user:)",
459
afs_com_err(progname, status, " while getting realm");
460
return(AKLOG_KERBEROS);
467
/* Cell on command line - use that one */
468
if (realm && realm[0]) {
469
realm_of_cell = realm;
470
status = AKLOG_TRYAGAIN;
472
printf("We were told to authenticate to realm %s.\n",
476
/* Initially, try using afs/cell@USERREALM */
478
printf("Trying to authenticate to user's realm %s.\n",
482
realm_of_cell = realm_of_user;
483
status = get_credv5(context, AFSKEY, cell_to_use,
581
484
realm_of_cell, &v5cred);
486
/* If that failed, try to determine the realm from the name of
487
* one of the DB servers */
488
if (TRYAGAIN(status)) {
489
realm_of_cell = afs_realm_of_cell(context, &ak_cellconfig,
491
if (!realm_of_cell) {
493
"%s: Couldn't figure out realm for cell %s.\n",
494
progname, cell_to_use);
499
if (realm_of_cell[0])
500
printf("We've deduced that we need to authenticate"
501
" to realm %s.\n", realm_of_cell);
503
printf("We've deduced that we need to authenticate "
504
"using referrals.\n");
509
if (TRYAGAIN(status)) {
510
/* If we've got the full-princ-first option, or we're in a
511
* different realm from the cell - use the cell name as the
513
if (AFS_TRY_FULL_PRINC ||
514
strcasecmp(cell_to_use, realm_of_cell)!=0) {
515
status = get_credv5(context, AFSKEY, cell_to_use,
516
realm_of_cell, &v5cred);
518
/* If we failed & we've got an empty realm, then try
519
* calling afs_realm_for_cell again. */
520
if (TRYAGAIN(status) && !realm_of_cell[0]) {
521
/* This time, get the realm by taking the domain
522
* component of the db server and make it upper case */
523
realm_of_cell = afs_realm_of_cell(context,
524
&ak_cellconfig, TRUE);
525
if (!realm_of_cell) {
527
"%s: Couldn't figure out realm for cell "
528
"%s.\n", progname, cell_to_use);
531
printf("We've deduced that we need to authenticate to"
532
" realm %s.\n", realm_of_cell);
534
status = get_credv5(context, AFSKEY, cell_to_use,
535
realm_of_cell, &v5cred);
538
/* If the realm and cell name match, then try without an
539
* instance, but only if realm is non-empty */
541
if (TRYAGAIN(status) &&
542
strcasecmp(cell_to_use, realm_of_cell) == 0) {
543
status = get_credv5(context, AFSKEY, NULL,
544
realm_of_cell, &v5cred);
545
if (!AFS_TRY_FULL_PRINC && TRYAGAIN(status)) {
546
status = get_credv5(context, AFSKEY, cell_to_use,
547
realm_of_cell, &v5cred);
552
/* Try to find a service principal for this cell.
553
* Some broken MIT libraries return KRB5KRB_AP_ERR_MSG_TYPE upon
554
* the first attempt, so we try twice to be sure */
556
if (status == KRB5KRB_AP_ERR_MSG_TYPE && retry == 1)
587
printf("Kerberos error code returned by get_cred: %d\n",
564
printf("Kerberos error code returned by get_cred : %d\n",
590
567
fprintf(stderr, "%s: Couldn't get %s AFS tickets:\n",
591
568
progname, cell_to_use);
592
com_err(progname, status, "while getting AFS tickets");
569
afs_com_err(progname, status, "while getting AFS tickets");
593
570
return(AKLOG_KERBEROS);
573
/* If we've got a valid ticket, and we still don't know the realm name
574
* try to figure it out from the contents of the ticket
576
#if !defined(USING_HEIMDAL) && defined(HAVE_KRB5_DECODE_TICKET)
577
if (strcmp(realm_of_cell, "") == 0) {
578
krb5_error_code code;
581
code = krb5_decode_ticket(&v5cred->ticket, &ticket);
585
"%s: Couldn't decode ticket to determine realm for "
587
progname, cell_to_use);
589
int len = realm_len(context, ticket->server);
590
/* This really shouldn't happen. */
591
if (len > REALM_SZ-1)
594
realm_from_princ = (char *) malloc(sizeof(char) * (len+1));
596
strncpy(realm_from_princ, realm_data(context, ticket->server),
598
realm_from_princ[len] = 0;
599
realm_of_cell = realm_from_princ;
601
krb5_free_ticket(context, ticket);
596
606
strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1);
597
607
strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1);
1503
static krb5_error_code get_credv5_akimpersonate(krb5_context context,
1505
krb5_principal service_principal,
1506
krb5_principal client_principal,
1509
int *allowed_enctypes,
1511
krb5_creds** out_creds /* out */ )
1513
#if defined(USING_HEIMDAL) || (defined(HAVE_ENCODE_KRB5_ENC_TKT) && defined(HAVE_ENCODE_KRB5_TICKET) && defined(HAVE_KRB5_C_ENCRYPT))
1514
krb5_error_code code;
1516
krb5_kt_cursor cursor[1];
1517
krb5_keytab_entry entry[1];
1519
krb5_creds *creds = 0;
1520
krb5_enctype enctype;
1522
krb5_keyblock session_key[1];
1524
Ticket ticket_reply[1];
1525
EncTicketPart enc_tkt_reply[1];
1526
krb5_address address[30];
1527
krb5_addresses faddr[1];
1529
time_t temp_time[2];
1531
krb5_ticket ticket_reply[1];
1532
krb5_enc_tkt_part enc_tkt_reply[1];
1533
krb5_address address[30], *faddr[30];
1537
static int any_enctype[] = {0};
1539
if (!(creds = malloc(sizeof *creds))) {
1543
if (!allowed_enctypes)
1544
allowed_enctypes = any_enctype;
1547
enctype = 0; /* AKIMPERSONATE_IGNORE_ENCTYPE */
1548
kvno = 0; /* AKIMPERSONATE_IGNORE_VNO */
1549
memset((char*)creds, 0, sizeof *creds);
1550
memset((char*)entry, 0, sizeof *entry);
1551
memset((char*)session_key, 0, sizeof *session_key);
1552
memset((char*)ticket_reply, 0, sizeof *ticket_reply);
1553
memset((char*)enc_tkt_reply, 0, sizeof *enc_tkt_reply);
1554
code = krb5_kt_resolve(context, keytab, &kt);
1557
afs_com_err(progname, code, "while resolving keytab %s", keytab);
1559
afs_com_err(progname, code, "while resolving default keytab");
1563
if (service_principal) {
1564
for (i = 0; (enctype = allowed_enctypes[i]) || !i; ++i) {
1565
code = krb5_kt_get_entry(context,
1572
if (allowed_enctypes[i])
1573
deref_keyblock_enctype(session_key) = allowed_enctypes[i];
1578
afs_com_err(progname, code,"while scanning keytab entries");
1582
krb5_keytab_entry new[1];
1584
memset(new, 0, sizeof *new);
1585
if ((code == krb5_kt_start_seq_get(context, kt, cursor))) {
1586
afs_com_err(progname, code, "while starting keytab scan");
1589
while (!(code = krb5_kt_next_entry(context, kt, new, cursor))) {
1591
allowed_enctypes[i] && allowed_enctypes[i]
1592
!= deref_entry_enctype(new); ++i)
1594
if ((!i || allowed_enctypes[i]) &&
1595
(best < 0 || best > i)) {
1596
krb5_free_keytab_entry_contents(context, entry);
1598
memset(new, 0, sizeof *new);
1599
} else krb5_free_keytab_entry_contents(context, new);
1601
if ((i = krb5_kt_end_seq_get(context, kt, cursor))) {
1602
afs_com_err(progname, i, "while ending keytab scan");
1607
afs_com_err(progname, code, "while scanning keytab");
1610
deref_keyblock_enctype(session_key) = deref_entry_enctype(entry);
1616
if ((code = krb5_generate_random_keyblock(context,
1617
deref_keyblock_enctype(session_key), session_key))) {
1618
afs_com_err(progname, code, "while making session key");
1621
enc_tkt_reply->flags.initial = 1;
1622
enc_tkt_reply->transited.tr_type = DOMAIN_X500_COMPRESS;
1623
enc_tkt_reply->cname = client_principal->name;
1624
enc_tkt_reply->crealm = client_principal->realm;
1625
enc_tkt_reply->key = *session_key;
1627
static krb5_data empty_string;
1628
enc_tkt_reply->transited.contents = empty_string;
1630
enc_tkt_reply->authtime = starttime;
1631
enc_tkt_reply->starttime = temp_time;
1632
*enc_tkt_reply->starttime = starttime;
1634
enc_tkt_reply->renew_till = temp_time + 1;
1635
*enc_tkt_reply->renew_till = endtime;
1637
enc_tkt_reply->endtime = endtime;
1639
if ((code = krb5_c_make_random_key(context,
1640
deref_keyblock_enctype(session_key), session_key))) {
1641
afs_com_err(progname, code, "while making session key");
1644
enc_tkt_reply->magic = KV5M_ENC_TKT_PART;
1645
#define DATACAST (unsigned char *)
1646
enc_tkt_reply->flags |= TKT_FLG_INITIAL;
1647
enc_tkt_reply->transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
1648
enc_tkt_reply->session = session_key;
1649
enc_tkt_reply->client = client_principal;
1651
static krb5_data empty_string;
1652
enc_tkt_reply->transited.tr_contents = empty_string;
1654
enc_tkt_reply->times.authtime = starttime;
1655
enc_tkt_reply->times.starttime = starttime; /* krb524init needs this */
1656
enc_tkt_reply->times.endtime = endtime;
1657
#endif /* USING_HEIMDAL */
1658
/* NB: We will discard address for now--ignoring caddr field
1659
in any case. MIT branch does what it always did. */
1661
if (paddress && *paddress) {
1662
deref_enc_tkt_addrs(enc_tkt_reply) = faddr;
1665
faddr->val = address;
1667
for (i = 0; paddress[i]; ++i) {
1669
address[i].addr_type = KRB5_ADDRESS_INET;
1670
address[i].address.data = (void*)(paddress+i);
1671
address[i].address.length = sizeof(paddress[i]);
1674
address[i].magic = KV5M_ADDRESS;
1675
address[i].addrtype = ADDRTYPE_INET;
1677
address[i].addrtype = AF_INET;
1679
address[i].contents = (void*)(paddress+i);
1680
address[i].length = sizeof(int);
1681
faddr[i] = address+i;
1692
ticket_reply->sname = service_principal->name;
1693
ticket_reply->realm = service_principal->realm;
1695
{ /* crypto block */
1696
krb5_crypto crypto = 0;
1697
unsigned char *buf = 0;
1698
size_t buf_size, buf_len;
1701
ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size,
1702
enc_tkt_reply, &buf_len, code);
1704
afs_com_err(progname, code, "while encoding ticket");
1708
if(buf_len != buf_size) {
1709
afs_com_err(progname, code,
1710
"%d != %d while encoding ticket (internal ASN.1 encoder error",
1714
what = "krb5_crypto_init";
1715
code = krb5_crypto_init(context,
1716
&deref_entry_keyblock(entry),
1717
deref_entry_enctype(entry),
1720
what = "krb5_encrypt";
1721
code = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_TICKET,
1722
buf, buf_len, entry->vno, &(ticket_reply->enc_part));
1725
if (crypto) krb5_crypto_destroy(context, crypto);
1727
afs_com_err(progname, code, "while %s", what);
1730
} /* crypto block */
1731
ticket_reply->enc_part.etype = deref_entry_enctype(entry);
1732
ticket_reply->enc_part.kvno = temp_vno;
1733
*ticket_reply->enc_part.kvno = entry->vno;
1734
ticket_reply->tkt_vno = 5;
1736
ticket_reply->server = service_principal;
1737
ticket_reply->enc_part2 = enc_tkt_reply;
1738
if ((code = krb5_encrypt_tkt_part(context, &deref_entry_keyblock(entry), ticket_reply))) {
1739
afs_com_err(progname, code, "while making ticket");
1742
ticket_reply->enc_part.kvno = entry->vno;
1745
/* Construct Creds */
1747
if ((code = krb5_copy_principal(context, service_principal,
1749
afs_com_err(progname, code, "while copying service principal");
1752
if ((code = krb5_copy_principal(context, client_principal,
1754
afs_com_err(progname, code, "while copying client principal");
1757
if ((code = krb5_copy_keyblock_contents(context, session_key,
1758
&deref_session_key(creds)))) {
1759
afs_com_err(progname, code, "while copying session key");
1764
creds->times.authtime = enc_tkt_reply->authtime;
1765
creds->times.starttime = *(enc_tkt_reply->starttime);
1766
creds->times.endtime = enc_tkt_reply->endtime;
1767
creds->times.renew_till = 0; /* *(enc_tkt_reply->renew_till) */
1768
creds->flags.b = enc_tkt_reply->flags;
1770
creds->times = enc_tkt_reply->times;
1771
creds->ticket_flags = enc_tkt_reply->flags;
1773
if (!deref_enc_tkt_addrs(enc_tkt_reply))
1775
else if ((code = krb5_copy_addresses(context,
1776
deref_enc_tkt_addrs(enc_tkt_reply), &creds->addresses))) {
1777
afs_com_err(progname, code, "while copying addresses");
1783
size_t creds_tkt_len;
1784
ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
1785
ticket_reply, &creds_tkt_len, code);
1787
afs_com_err(progname, code, "while encoding ticket");
1792
if ((code = encode_krb5_ticket(ticket_reply, &temp))) {
1793
afs_com_err(progname, code, "while encoding ticket");
1796
creds->ticket = *temp;
1803
if (deref_enc_data(&ticket_reply->enc_part))
1804
free(deref_enc_data(&ticket_reply->enc_part));
1805
krb5_free_keytab_entry_contents(context, entry);
1806
if (client_principal)
1807
krb5_free_principal(context, client_principal);
1808
if (service_principal)
1809
krb5_free_principal(context, service_principal);
1811
krb5_cc_close(context, cc);
1813
krb5_kt_close(context, kt);
1814
if (creds) krb5_free_creds(context, creds);
1815
krb5_free_keyblock_contents(context, session_key);
1557
1824
static krb5_error_code get_credv5(krb5_context context,
1558
char *name, char *inst, char *realm,
1825
char *name, char *inst, char *realm,
1561
1828
krb5_creds increds;
1562
1829
krb5_error_code r;
1563
1830
static krb5_principal client_principal = 0;
1833
printf("Getting tickets: %s%s%s@%s\n", name, (inst && inst[0])
1834
? "/" : "", inst ? inst : "", realm);
1565
1837
memset((char *)&increds, 0, sizeof(increds));
1566
1838
/* ANL - instance may be ptr to a null string. Pass null then */
1567
1839
if ((r = krb5_build_principal(context, &increds.server,
1568
strlen(realm), realm,
1570
(inst && strlen(inst)) ? inst : (void *) NULL,
1840
strlen(realm), realm,
1842
(inst && strlen(inst)) ? inst : (void *) NULL,
1575
1848
if (!_krb425_ccache) {
1576
1849
r = krb5_cc_default(context, &_krb425_ccache);