1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright (c) 1994 by the University of Southern California 4 * 5 * EXPORT OF THIS SOFTWARE from the United States of America may 6 * require a specific license from the United States Government. 7 * It is the responsibility of any person or organization contemplating 8 * export to obtain such a license before exporting. 9 * 10 * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute 11 * this software and its documentation in source and binary forms is 12 * hereby granted, provided that any documentation or other materials 13 * related to such distribution or use acknowledge that the software 14 * was developed by the University of Southern California. 15 * 16 * DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The 17 * University of Southern California MAKES NO REPRESENTATIONS OR 18 * WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not 19 * limitation, the University of Southern California MAKES NO 20 * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY 21 * PARTICULAR PURPOSE. The University of Southern 22 * California shall not be held liable for any liability nor for any 23 * direct, indirect, or consequential damages with respect to any 24 * claim by the user or distributor of the ksu software. 25 * 26 * KSU was written by: Ari Medvinsky, ari@isi.edu 27 */ 28 29 #include "ksu.h" 30 31 32 void plain_dump_principal (); 33 34 krb5_boolean krb5_auth_check(context, client_pname, hostname, options, 35 target_user, cc, path_passwd, target_uid) 36 krb5_context context; 37 krb5_principal client_pname; 38 char *hostname; 39 krb5_get_init_creds_opt *options; 40 char *target_user; 41 uid_t target_uid; 42 krb5_ccache cc; 43 int *path_passwd; 44 { 45 krb5_principal client; 46 krb5_verify_init_creds_opt vfy_opts; 47 krb5_creds tgt, tgtq; 48 krb5_error_code retval =0; 49 int got_it = 0; 50 krb5_boolean zero_password; 51 52 *path_passwd = 0; 53 memset(&tgtq, 0, sizeof(tgtq)); 54 memset(&tgt, 0, sizeof(tgt)); 55 56 if ((retval= krb5_copy_principal(context, client_pname, &client))){ 57 com_err(prog_name, retval, _("while copying client principal")); 58 return (FALSE) ; 59 } 60 61 if ((retval= krb5_copy_principal(context, client, &tgtq.client))){ 62 com_err(prog_name, retval, _("while copying client principal")); 63 return (FALSE) ; 64 } 65 66 if ((retval = ksu_tgtname(context, krb5_princ_realm(context, client), 67 krb5_princ_realm(context, client), 68 &tgtq.server))){ 69 com_err(prog_name, retval, _("while creating tgt for local realm")); 70 krb5_free_principal(context, client); 71 return (FALSE) ; 72 } 73 74 if (auth_debug){ dump_principal(context, "local tgt principal name", tgtq.server ); } 75 retval = krb5_cc_retrieve_cred(context, cc, 76 KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES, 77 &tgtq, &tgt); 78 79 if (! retval) retval = krb5_check_exp(context, tgt.times); 80 81 if (retval){ 82 if ((retval != KRB5_CC_NOTFOUND) && 83 (retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){ 84 com_err(prog_name, retval, _("while retrieving creds from cache")); 85 return (FALSE) ; 86 } 87 } else{ 88 got_it = 1; 89 } 90 91 if (! got_it){ 92 93 #ifdef GET_TGT_VIA_PASSWD 94 if (krb5_seteuid(0)||krb5_seteuid(target_uid)) { 95 com_err("ksu", errno, _("while switching to target uid")); 96 return FALSE; 97 } 98 99 100 fprintf(stderr, _("WARNING: Your password may be exposed if you enter " 101 "it here and are logged \n")); 102 fprintf(stderr, _(" in remotely using an unsecure " 103 "(non-encrypted) channel. \n")); 104 105 /*get the ticket granting ticket, via passwd(prompt for passwd)*/ 106 if (ksu_get_tgt_via_passwd(context, client, options, &zero_password, 107 &tgt) == FALSE) { 108 krb5_seteuid(0); 109 110 return FALSE; 111 } 112 *path_passwd = 1; 113 if (krb5_seteuid(0)) { 114 com_err("ksu", errno, _("while reclaiming root uid")); 115 return FALSE; 116 } 117 118 #else 119 plain_dump_principal (context, client); 120 fprintf(stderr, 121 _("does not have any appropriate tickets in the cache.\n")); 122 return FALSE; 123 124 #endif /* GET_TGT_VIA_PASSWD */ 125 126 } 127 128 krb5_verify_init_creds_opt_init(&vfy_opts); 129 krb5_verify_init_creds_opt_set_ap_req_nofail( &vfy_opts, 1); 130 retval = krb5_verify_init_creds(context, &tgt, NULL, NULL, NULL, 131 &vfy_opts); 132 if (retval) { 133 com_err(prog_name, retval, _("while verifying ticket for server")); 134 return (FALSE); 135 } 136 137 return (TRUE); 138 } 139 140 krb5_boolean ksu_get_tgt_via_passwd(context, client, options, zero_password, 141 creds_out) 142 krb5_context context; 143 krb5_principal client; 144 krb5_get_init_creds_opt *options; 145 krb5_boolean *zero_password; 146 krb5_creds *creds_out; 147 { 148 krb5_error_code code; 149 krb5_creds creds; 150 krb5_timestamp now; 151 unsigned int pwsize; 152 char password[255], *client_name, prompt[255]; 153 int result; 154 155 *zero_password = FALSE; 156 if (creds_out != NULL) 157 memset(creds_out, 0, sizeof(*creds_out)); 158 159 if ((code = krb5_unparse_name(context, client, &client_name))) { 160 com_err (prog_name, code, _("when unparsing name")); 161 return (FALSE); 162 } 163 164 memset(&creds, 0, sizeof(creds)); 165 166 if ((code = krb5_timeofday(context, &now))) { 167 com_err(prog_name, code, _("while getting time of day")); 168 return (FALSE); 169 } 170 171 result = snprintf(prompt, sizeof(prompt), _("Kerberos password for %s: "), 172 client_name); 173 if (SNPRINTF_OVERFLOW(result, sizeof(prompt))) { 174 fprintf(stderr, 175 _("principal name %s too long for internal buffer space\n"), 176 client_name); 177 return FALSE; 178 } 179 180 pwsize = sizeof(password); 181 182 code = krb5_read_password(context, prompt, 0, password, &pwsize); 183 if (code ) { 184 com_err(prog_name, code, _("while reading password for '%s'\n"), 185 client_name); 186 return (FALSE); 187 } 188 189 if ( pwsize == 0) { 190 fprintf(stderr, _("No password given\n")); 191 *zero_password = TRUE; 192 return (FALSE); 193 } 194 195 code = krb5_get_init_creds_password(context, &creds, client, password, 196 krb5_prompter_posix, NULL, 0, NULL, 197 options); 198 zap(password, sizeof(password)); 199 200 201 if (code) { 202 if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) 203 fprintf(stderr, _("%s: Password incorrect\n"), prog_name); 204 else 205 com_err(prog_name, code, _("while getting initial credentials")); 206 return (FALSE); 207 } 208 if (creds_out != NULL) 209 *creds_out = creds; 210 else 211 krb5_free_cred_contents(context, &creds); 212 return (TRUE); 213 } 214 215 216 void dump_principal (context, str, p) 217 krb5_context context; 218 char *str; 219 krb5_principal p; 220 { 221 char * stname; 222 krb5_error_code retval; 223 224 if ((retval = krb5_unparse_name(context, p, &stname))) { 225 fprintf(stderr, _(" %s while unparsing name\n"), 226 error_message(retval)); 227 } 228 fprintf(stderr, " %s: %s\n", str, stname); 229 } 230 231 void plain_dump_principal (context, p) 232 krb5_context context; 233 krb5_principal p; 234 { 235 char * stname; 236 krb5_error_code retval; 237 238 if ((retval = krb5_unparse_name(context, p, &stname))) { 239 fprintf(stderr, _(" %s while unparsing name\n"), 240 error_message(retval)); 241 } 242 fprintf(stderr, "%s ", stname); 243 } 244 245 246 /********************************************************************** 247 returns the principal that is closest to client. plist contains 248 a principal list obtained from .k5login and parhaps .k5users file. 249 This routine gets called before getting the password for a tgt. 250 A principal is picked that has the best chance of getting in. 251 252 **********************************************************************/ 253 254 255 krb5_error_code get_best_principal(context, plist, client) 256 krb5_context context; 257 char **plist; 258 krb5_principal *client; 259 { 260 krb5_error_code retval =0; 261 krb5_principal temp_client, best_client = NULL; 262 263 int i = 0, nelem; 264 265 if (! plist ) return 0; 266 267 nelem = krb5_princ_size(context, *client); 268 269 while(plist[i]){ 270 271 if ((retval = krb5_parse_name(context, plist[i], &temp_client))){ 272 return retval; 273 } 274 275 if (data_eq(*krb5_princ_realm(context, *client), 276 *krb5_princ_realm(context, temp_client))) { 277 278 if (nelem && 279 krb5_princ_size(context, *client) > 0 && 280 krb5_princ_size(context, temp_client) > 0) { 281 krb5_data *p1 = 282 krb5_princ_component(context, *client, 0); 283 krb5_data *p2 = 284 krb5_princ_component(context, temp_client, 0); 285 286 if (data_eq(*p1, *p2)) { 287 288 if (auth_debug){ 289 fprintf(stderr, 290 "get_best_principal: compare with %s\n", 291 plist[i]); 292 } 293 294 if(best_client){ 295 if(krb5_princ_size(context, best_client) > 296 krb5_princ_size(context, temp_client)){ 297 best_client = temp_client; 298 } 299 }else{ 300 best_client = temp_client; 301 } 302 } 303 } 304 305 } 306 i++; 307 } 308 309 if (best_client) *client = best_client; 310 return 0; 311 } 312