/* aklog.c: request a Kerberos ticket grant for an AFS cell * * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include #include #include #include #include #include #include #include extern int krb524_convert_creds_kdc(krb5_context, krb5_creds *, CREDENTIALS *); char *realm = "CAMBRIDGE.REDHAT.COM"; //NULL; char *cell = "cambridge.redhat.com"; //NULL; int debug = 0; krb5_principal princ; krb5_context krb5context; krb5_ccache tktcache; static void format(void) __attribute__((noreturn)); static void format(void) { fprintf(stderr, "aklog [-d] [-c] [] [-k ]\n"); exit(2); } #define KRBERR(X,M) do { if ((X) != KSUCCESS) krberr((X),(M)); } while(0) void krberr(errcode_t kerr, const char *where) __attribute__((noreturn)); void krberr(errcode_t kerr, const char *where) { fprintf(stderr, "%s: %s\n", where, error_message(kerr)); exit(1); } /*****************************************************************************/ /* * parse the argument list */ void parse_args(char **argv) { if (!*argv) return; if (strcmp(argv[0], "-help") == 0) format(); if (strcmp(argv[0], "-d") == 0) { debug++; argv++; } if (strcmp(argv[0], "-c") == 0) argv++; if (!*argv) format(); if (argv[0][0] == '-') format(); cell = *argv; argv++; if (!*argv) return; if (strcmp(argv[0], "-k") != 0) format(); argv++; if (!*argv) return; if (argv[0][0] == '-') format(); realm = *argv; argv++; if (*argv) format(); } /* end parse_args() */ /*****************************************************************************/ /* * try to obtain a kerberos ticket */ int obtain_ticket(krb5_creds **creds, const char *service, const char *cell) { krb5_error_code kerr; krb5_creds request; /* set up a description of what we actually want */ memset(&request, 0, sizeof(request)); kerr = krb5_build_principal(krb5context, &request.server, strlen(realm), realm, service, cell, NULL); KRBERR(kerr, "failed to construct request"); request.client = princ; request.times.endtime = 0; request.keyblock.enctype = ENCTYPE_DES_CBC_CRC; /* go and prod the Kerberos servers */ kerr = krb5_get_credentials(krb5context, 0, tktcache, &request, creds); if (kerr != KSUCCESS && kerr != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) KRBERR(kerr, "error talking to KDC"); return kerr == KSUCCESS; } /* end obtain_ticket() */ /*****************************************************************************/ /* * */ int main(int argc, char *argv[]) { krb5_error_code kerr; unsigned char *cp; krb5_creds *creds5; CREDENTIALS creds4; time_t time; char buf1[100]; int loop; parse_args(argv + 1); kerr = krb5_init_context(&krb5context); KRBERR(kerr, "failed to initialise the Kerberos5 context"); /* may need to find the default realm */ if (!realm) { kerr = krb5_get_default_realm(krb5context, &realm); KRBERR(kerr, "failed to get the default realm"); } /* may need to find the default AFS cell */ if (!cell) { } /* open the appropriate Kerberos ticket cache */ kerr = krb5_cc_default(krb5context, &tktcache); KRBERR(kerr, "unable to resolve default cred cache"); kerr = krb5_cc_get_principal(krb5context, tktcache, &princ); KRBERR(kerr, "unable to extract the principal from the cache"); /* ask the KDC to give us an AFS ticket */ if (!cell || !obtain_ticket(&creds5, "afs", cell)) { if (!obtain_ticket(&creds5, "afs", NULL)) { fprintf(stderr, "couldn't obtain AFS ticket\n"); exit(2); } } kerr = krb5_cc_close(krb5context, tktcache); KRBERR(kerr, "error closing cache"); /* ask the KDC to turn the Kerberos 5 ticket into a Kerberos 4 * ticket */ kerr = krb524_convert_creds_kdc(krb5context, creds5, &creds4); KRBERR(kerr, "unable to convert to a kerberos V4 ticket"); /* dump the credential data obtained */ if (debug) { printf("SERVICE : %s%s%s@%s\n", creds4.service, creds4.instance[0] ? "/" : "", creds4.instance, creds4.realm); printf("PRINCIPAL: %s%s%s@%s\n", creds4.pname, creds4.pinst[0] ? "/" : "", creds4.pinst, creds4.realm); time = creds4.issue_date; printf("ISSUED : %s", ctime_r(&time, buf1)); time = creds5->times.endtime; printf("EXPIRES : %s", ctime_r(&time, buf1)); printf("SESSION : key=["); cp = (unsigned char *) &creds4.session; for (loop = 0; loop < sizeof(creds4.session); loop++) printf("%02x", *cp++); printf("]\n"); printf("TICKET : version %d, length %d:", creds4.kvno, creds4.ticket_st.length); cp = (unsigned char *) &creds4.ticket_st.dat; for (loop = 0; loop < creds4.ticket_st.length; loop++) { if (loop % (76 / 2) == 0) printf("\n "); printf("%02x", *cp++); } printf("\n"); } /* pass the ticket to the AFS filesystem */ if (afsutil_authorise_krb5(cell, realm, creds5->times.endtime, sizeof(creds4.session), &creds4.session, creds4.kvno, creds4.ticket_st.length, creds4.ticket_st.dat) < 0 ) { fprintf(stderr, "unable to pass token to kernel: %m\n"); exit(1); } krb5_free_creds(krb5context, creds5); krb5_free_context(krb5context); return 0; } /* end main() */