1 /* windows/ms2mit/ms2mit.c */ 2 /* 3 * Copyright (C) 2003 by the Massachusetts Institute of Technology. 4 * All rights reserved. 5 * 6 * Export of this software from the United States of America may 7 * require a specific license from the United States Government. 8 * It is the responsibility of any person or organization contemplating 9 * export to obtain such a license before exporting. 10 * 11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 12 * distribute this software and its documentation for any purpose and 13 * without fee is hereby granted, provided that the above copyright 14 * notice appear in all copies and that both that copyright notice and 15 * this permission notice appear in supporting documentation, and that 16 * the name of M.I.T. not be used in advertising or publicity pertaining 17 * to distribution of the software without specific, written prior 18 * permission. Furthermore if you modify this software you must label 19 * your software as modified software and not distribute it in such a 20 * fashion that it might be confused with the original M.I.T. software. 21 * M.I.T. makes no representations about the suitability of 22 * this software for any purpose. It is provided "as is" without express 23 * or implied warranty. 24 */ 25 26 #include "k5-int.h" 27 #include "krb5.h" 28 #include <stdio.h> 29 #include <string.h> 30 #include <time.h> 31 32 static char *prog; 33 34 static void 35 xusage(void) 36 { 37 fprintf(stderr, "xusage: %s [-c ccache]\n", prog); 38 exit(1); 39 } 40 41 /* Return true if princ is a local (not cross-realm) krbtgt principal. */ 42 krb5_boolean 43 is_local_tgt(krb5_principal princ) 44 { 45 return princ->length == 2 && 46 data_eq_string(princ->data[0], KRB5_TGS_NAME) && 47 data_eq(princ->realm, princ->data[1]); 48 } 49 50 /* 51 * Check if a ccache has any tickets. 52 */ 53 static krb5_error_code 54 cc_has_tickets(krb5_context kcontext, krb5_ccache ccache, int *has_tickets) 55 { 56 krb5_error_code code; 57 krb5_cc_cursor cursor; 58 krb5_creds creds; 59 krb5_timestamp now = time(0); 60 61 *has_tickets = 0; 62 63 code = krb5_cc_set_flags(kcontext, ccache, KRB5_TC_NOTICKET); 64 if (code) 65 return code; 66 67 code = krb5_cc_start_seq_get(kcontext, ccache, &cursor); 68 if (code) 69 return code; 70 71 while (!*has_tickets) { 72 code = krb5_cc_next_cred(kcontext, ccache, &cursor, &creds); 73 if (code) 74 break; 75 76 if (!krb5_is_config_principal(kcontext, creds.server) && 77 ts_after(creds.times.endtime, now)) 78 *has_tickets = 1; 79 80 krb5_free_cred_contents(kcontext, &creds); 81 } 82 krb5_cc_end_seq_get(kcontext, ccache, &cursor); 83 84 return 0; 85 } 86 87 int 88 main(int argc, char *argv[]) 89 { 90 krb5_context kcontext = NULL; 91 krb5_error_code code; 92 krb5_ccache ccache=NULL; 93 krb5_ccache mslsa_ccache=NULL; 94 krb5_cc_cursor cursor; 95 krb5_creds creds; 96 krb5_principal princ = NULL; 97 int found_tgt = 0; 98 int has_tickets; 99 int option; 100 char * ccachestr = 0; 101 102 prog = strrchr(argv[0], '/'); 103 prog = prog ? (prog + 1) : argv[0]; 104 105 while ((option = getopt(argc, argv, "c:h")) != -1) { 106 switch (option) { 107 case 'c': 108 ccachestr = optarg; 109 break; 110 case 'h': 111 default: 112 xusage(); 113 break; 114 } 115 } 116 117 if (code = krb5_init_context(&kcontext)) { 118 com_err(argv[0], code, "while initializing kerberos library"); 119 goto cleanup; 120 } 121 122 if (code = krb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) { 123 com_err(argv[0], code, "while opening MS LSA ccache"); 124 goto cleanup; 125 } 126 127 /* Enumerate tickets from cache looking for a TGT */ 128 if ((code = krb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) { 129 com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache"); 130 goto cleanup; 131 } 132 133 while (!found_tgt) { 134 code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds); 135 if (code) 136 break; 137 138 /* Check if the ticket is a TGT */ 139 if (is_local_tgt(creds.server)) 140 found_tgt = 1; 141 142 krb5_free_cred_contents(kcontext, &creds); 143 } 144 krb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor); 145 146 if (!found_tgt) { 147 fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MS LSA\n", 148 argv[0]); 149 /* Only set the LSA cache as the default if it actually has tickets. */ 150 code = cc_has_tickets(kcontext, mslsa_ccache, &has_tickets); 151 if (code) 152 goto cleanup; 153 154 if (has_tickets) 155 code = krb5int_cc_user_set_default_name(kcontext, "MSLSA:"); 156 157 goto cleanup; 158 } 159 160 if (code = krb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) { 161 com_err(argv[0], code, "while obtaining MS LSA principal"); 162 goto cleanup; 163 } 164 165 if (ccachestr) 166 code = krb5_cc_resolve(kcontext, ccachestr, &ccache); 167 else 168 code = krb5_cc_resolve(kcontext, "API:", &ccache); 169 if (code) { 170 com_err(argv[0], code, "while getting default ccache"); 171 goto cleanup; 172 } 173 if (code = krb5_cc_initialize(kcontext, ccache, princ)) { 174 com_err (argv[0], code, "when initializing ccache"); 175 goto cleanup; 176 } 177 178 if (code = krb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) { 179 com_err (argv[0], code, "while copying MS LSA ccache to default ccache"); 180 goto cleanup; 181 } 182 183 /* Don't try and set the default cache if the cache name was specified. */ 184 if (ccachestr == NULL) { 185 /* On success set the default cache to API. */ 186 code = krb5int_cc_user_set_default_name(kcontext, "API:"); 187 if (code) { 188 com_err(argv[0], code, "when setting default to API"); 189 goto cleanup; 190 } 191 } 192 193 cleanup: 194 krb5_free_principal(kcontext, princ); 195 if (ccache != NULL) 196 krb5_cc_close(kcontext, ccache); 197 if (mslsa_ccache != NULL) 198 krb5_cc_close(kcontext, mslsa_ccache); 199 krb5_free_context(kcontext); 200 return code ? 1 : 0; 201 } 202