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(krb5_context, krb5_principal); 33 34 krb5_boolean 35 krb5_auth_check(krb5_context context, krb5_principal client_pname, 36 char *hostname, krb5_get_init_creds_opt *options, 37 char *target_user, krb5_ccache cc, int *path_passwd, 38 uid_t target_uid) 39 { 40 krb5_principal client = NULL; 41 krb5_verify_init_creds_opt vfy_opts; 42 krb5_creds tgt = { 0 }, tgtq = { 0 }; 43 krb5_error_code retval =0; 44 int got_it = 0; 45 krb5_boolean zero_password; 46 krb5_boolean ok = FALSE; 47 48 *path_passwd = 0; 49 50 if ((retval= krb5_copy_principal(context, client_pname, &client))){ 51 com_err(prog_name, retval, _("while copying client principal")); 52 goto cleanup; 53 } 54 55 if ((retval= krb5_copy_principal(context, client, &tgtq.client))){ 56 com_err(prog_name, retval, _("while copying client principal")); 57 goto cleanup; 58 } 59 60 if ((retval = ksu_tgtname(context, krb5_princ_realm(context, client), 61 krb5_princ_realm(context, client), 62 &tgtq.server))){ 63 com_err(prog_name, retval, _("while creating tgt for local realm")); 64 goto cleanup; 65 } 66 67 if (auth_debug){ dump_principal(context, "local tgt principal name", tgtq.server ); } 68 retval = krb5_cc_retrieve_cred(context, cc, 69 KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES, 70 &tgtq, &tgt); 71 72 if (! retval) retval = krb5_check_exp(context, tgt.times); 73 74 if (retval){ 75 if ((retval != KRB5_CC_NOTFOUND) && 76 (retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){ 77 com_err(prog_name, retval, _("while retrieving creds from cache")); 78 goto cleanup; 79 } 80 } else{ 81 got_it = 1; 82 } 83 84 if (! got_it){ 85 86 #ifdef GET_TGT_VIA_PASSWD 87 if (krb5_seteuid(0)||krb5_seteuid(target_uid)) { 88 com_err("ksu", errno, _("while switching to target uid")); 89 goto cleanup; 90 } 91 92 93 fprintf(stderr, _("WARNING: Your password may be exposed if you enter " 94 "it here and are logged \n")); 95 fprintf(stderr, _(" in remotely using an unsecure " 96 "(non-encrypted) channel. \n")); 97 98 /*get the ticket granting ticket, via passwd(prompt for passwd)*/ 99 if (ksu_get_tgt_via_passwd(context, client, options, &zero_password, 100 &tgt) == FALSE) { 101 krb5_seteuid(0); 102 103 goto cleanup; 104 } 105 *path_passwd = 1; 106 if (krb5_seteuid(0)) { 107 com_err("ksu", errno, _("while reclaiming root uid")); 108 goto cleanup; 109 } 110 111 #else 112 plain_dump_principal (context, client); 113 fprintf(stderr, 114 _("does not have any appropriate tickets in the cache.\n")); 115 goto cleanup; 116 117 #endif /* GET_TGT_VIA_PASSWD */ 118 119 } 120 121 krb5_verify_init_creds_opt_init(&vfy_opts); 122 krb5_verify_init_creds_opt_set_ap_req_nofail( &vfy_opts, 1); 123 retval = krb5_verify_init_creds(context, &tgt, NULL, NULL, NULL, 124 &vfy_opts); 125 if (retval) { 126 com_err(prog_name, retval, _("while verifying ticket for server")); 127 goto cleanup; 128 } 129 130 ok = TRUE; 131 132 cleanup: 133 krb5_free_principal(context, client); 134 krb5_free_cred_contents(context, &tgt); 135 krb5_free_cred_contents(context, &tgtq); 136 return ok; 137 } 138 139 krb5_boolean 140 ksu_get_tgt_via_passwd(krb5_context context, krb5_principal client, 141 krb5_get_init_creds_opt *options, 142 krb5_boolean *zero_password, krb5_creds *creds_out) 143 { 144 krb5_boolean ok = FALSE; 145 krb5_error_code code; 146 krb5_creds creds = { 0 }; 147 krb5_timestamp now; 148 unsigned int pwsize; 149 char password[255], prompt[255], *client_name = NULL; 150 int result; 151 152 *zero_password = FALSE; 153 if (creds_out != NULL) 154 memset(creds_out, 0, sizeof(*creds_out)); 155 156 if ((code = krb5_unparse_name(context, client, &client_name))) { 157 com_err (prog_name, code, _("when unparsing name")); 158 goto cleanup; 159 } 160 161 memset(&creds, 0, sizeof(creds)); 162 163 if ((code = krb5_timeofday(context, &now))) { 164 com_err(prog_name, code, _("while getting time of day")); 165 goto cleanup; 166 } 167 168 result = snprintf(prompt, sizeof(prompt), _("Kerberos password for %s: "), 169 client_name); 170 if (SNPRINTF_OVERFLOW(result, sizeof(prompt))) { 171 fprintf(stderr, 172 _("principal name %s too long for internal buffer space\n"), 173 client_name); 174 goto cleanup; 175 } 176 177 pwsize = sizeof(password); 178 179 code = krb5_read_password(context, prompt, 0, password, &pwsize); 180 if (code ) { 181 com_err(prog_name, code, _("while reading password for '%s'\n"), 182 client_name); 183 goto cleanup; 184 } 185 186 if ( pwsize == 0) { 187 fprintf(stderr, _("No password given\n")); 188 *zero_password = TRUE; 189 goto cleanup; 190 } 191 192 code = krb5_get_init_creds_password(context, &creds, client, password, 193 krb5_prompter_posix, NULL, 0, NULL, 194 options); 195 zap(password, sizeof(password)); 196 197 198 if (code) { 199 if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) 200 fprintf(stderr, _("%s: Password incorrect\n"), prog_name); 201 else 202 com_err(prog_name, code, _("while getting initial credentials")); 203 goto cleanup; 204 } 205 if (creds_out != NULL) { 206 *creds_out = creds; 207 memset(&creds, 0, sizeof(creds)); 208 } 209 210 ok = TRUE; 211 212 cleanup: 213 krb5_free_cred_contents(context, &creds); 214 free(client_name); 215 return ok; 216 } 217 218 void 219 dump_principal(krb5_context context, char *str, 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 return; 228 } 229 fprintf(stderr, " %s: %s\n", str, stname); 230 free(stname); 231 } 232 233 void 234 plain_dump_principal (krb5_context context, krb5_principal p) 235 { 236 char * stname; 237 krb5_error_code retval; 238 239 if ((retval = krb5_unparse_name(context, p, &stname))) { 240 fprintf(stderr, _(" %s while unparsing name\n"), 241 error_message(retval)); 242 return; 243 } 244 fprintf(stderr, "%s ", stname); 245 free(stname); 246 } 247