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