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 #ifdef HAVE_UNISTD_H
32*7f2fe78bSCy Schubert #include <unistd.h>
33*7f2fe78bSCy Schubert #endif
34*7f2fe78bSCy Schubert
35*7f2fe78bSCy Schubert
36*7f2fe78bSCy Schubert /*******************************************************************
37*7f2fe78bSCy Schubert get_all_princ_from_file - retrieves all principal names
38*7f2fe78bSCy Schubert from file pointed to by fp.
39*7f2fe78bSCy Schubert
40*7f2fe78bSCy Schubert *******************************************************************/
41*7f2fe78bSCy Schubert static void close_time (int, FILE *, int, FILE *);
42*7f2fe78bSCy Schubert static krb5_boolean find_str_in_list (char **, char *);
43*7f2fe78bSCy Schubert
get_all_princ_from_file(fp,plist)44*7f2fe78bSCy Schubert krb5_error_code get_all_princ_from_file (fp, plist)
45*7f2fe78bSCy Schubert FILE *fp;
46*7f2fe78bSCy Schubert char ***plist;
47*7f2fe78bSCy Schubert {
48*7f2fe78bSCy Schubert
49*7f2fe78bSCy Schubert krb5_error_code retval;
50*7f2fe78bSCy Schubert char * line, * fprinc, * lp, ** temp_list = NULL;
51*7f2fe78bSCy Schubert int count = 0, chunk_count = 1;
52*7f2fe78bSCy Schubert
53*7f2fe78bSCy Schubert if (!(temp_list = (char **) malloc( CHUNK * sizeof(char *))))
54*7f2fe78bSCy Schubert return ENOMEM;
55*7f2fe78bSCy Schubert
56*7f2fe78bSCy Schubert retval = get_line(fp, &line);
57*7f2fe78bSCy Schubert if (retval)
58*7f2fe78bSCy Schubert return retval;
59*7f2fe78bSCy Schubert
60*7f2fe78bSCy Schubert while (line){
61*7f2fe78bSCy Schubert fprinc = get_first_token (line, &lp);
62*7f2fe78bSCy Schubert
63*7f2fe78bSCy Schubert if (fprinc ){
64*7f2fe78bSCy Schubert temp_list[count] = xstrdup(fprinc);
65*7f2fe78bSCy Schubert count ++;
66*7f2fe78bSCy Schubert }
67*7f2fe78bSCy Schubert
68*7f2fe78bSCy Schubert if(count == (chunk_count * CHUNK -1)){
69*7f2fe78bSCy Schubert chunk_count ++;
70*7f2fe78bSCy Schubert if (!(temp_list = (char **) realloc(temp_list,
71*7f2fe78bSCy Schubert chunk_count * CHUNK * sizeof(char *)))){
72*7f2fe78bSCy Schubert return ENOMEM;
73*7f2fe78bSCy Schubert }
74*7f2fe78bSCy Schubert }
75*7f2fe78bSCy Schubert
76*7f2fe78bSCy Schubert
77*7f2fe78bSCy Schubert free (line);
78*7f2fe78bSCy Schubert retval = get_line(fp, &line);
79*7f2fe78bSCy Schubert if (retval)
80*7f2fe78bSCy Schubert return retval;
81*7f2fe78bSCy Schubert }
82*7f2fe78bSCy Schubert
83*7f2fe78bSCy Schubert temp_list[count] = NULL;
84*7f2fe78bSCy Schubert
85*7f2fe78bSCy Schubert *plist = temp_list;
86*7f2fe78bSCy Schubert return 0;
87*7f2fe78bSCy Schubert }
88*7f2fe78bSCy Schubert
89*7f2fe78bSCy Schubert /*************************************************************
90*7f2fe78bSCy Schubert list_union - combines list1 and list2 into combined_list.
91*7f2fe78bSCy Schubert the space for list1 and list2 is either freed
92*7f2fe78bSCy Schubert or used by combined_list.
93*7f2fe78bSCy Schubert **************************************************************/
94*7f2fe78bSCy Schubert
list_union(list1,list2,combined_list)95*7f2fe78bSCy Schubert krb5_error_code list_union(list1, list2, combined_list)
96*7f2fe78bSCy Schubert char **list1;
97*7f2fe78bSCy Schubert char **list2;
98*7f2fe78bSCy Schubert char ***combined_list;
99*7f2fe78bSCy Schubert {
100*7f2fe78bSCy Schubert
101*7f2fe78bSCy Schubert unsigned int c1 =0, c2 = 0, i=0, j=0;
102*7f2fe78bSCy Schubert char ** tlist;
103*7f2fe78bSCy Schubert
104*7f2fe78bSCy Schubert if (! list1){
105*7f2fe78bSCy Schubert *combined_list = list2;
106*7f2fe78bSCy Schubert return 0;
107*7f2fe78bSCy Schubert }
108*7f2fe78bSCy Schubert
109*7f2fe78bSCy Schubert if (! list2){
110*7f2fe78bSCy Schubert *combined_list = list1;
111*7f2fe78bSCy Schubert return 0;
112*7f2fe78bSCy Schubert }
113*7f2fe78bSCy Schubert
114*7f2fe78bSCy Schubert while (list1[c1]) c1++;
115*7f2fe78bSCy Schubert while (list2[c2]) c2++;
116*7f2fe78bSCy Schubert
117*7f2fe78bSCy Schubert if (!(tlist = (char **) calloc( c1 + c2 + 1, sizeof ( char *))))
118*7f2fe78bSCy Schubert return ENOMEM;
119*7f2fe78bSCy Schubert
120*7f2fe78bSCy Schubert i = 0;
121*7f2fe78bSCy Schubert while(list1[i]) {
122*7f2fe78bSCy Schubert tlist[i] = list1[i];
123*7f2fe78bSCy Schubert i++;
124*7f2fe78bSCy Schubert }
125*7f2fe78bSCy Schubert j = 0;
126*7f2fe78bSCy Schubert while(list2[j]){
127*7f2fe78bSCy Schubert if(find_str_in_list(list1, list2[j])==FALSE){
128*7f2fe78bSCy Schubert tlist[i] = list2[j];
129*7f2fe78bSCy Schubert i++;
130*7f2fe78bSCy Schubert }
131*7f2fe78bSCy Schubert j++;
132*7f2fe78bSCy Schubert }
133*7f2fe78bSCy Schubert
134*7f2fe78bSCy Schubert free (list1);
135*7f2fe78bSCy Schubert free (list2);
136*7f2fe78bSCy Schubert
137*7f2fe78bSCy Schubert tlist[i]= NULL;
138*7f2fe78bSCy Schubert
139*7f2fe78bSCy Schubert *combined_list = tlist;
140*7f2fe78bSCy Schubert return 0;
141*7f2fe78bSCy Schubert }
142*7f2fe78bSCy Schubert
143*7f2fe78bSCy Schubert krb5_error_code
filter(fp,cmd,k5users_list,k5users_filt_list)144*7f2fe78bSCy Schubert filter(fp, cmd, k5users_list, k5users_filt_list)
145*7f2fe78bSCy Schubert FILE *fp;
146*7f2fe78bSCy Schubert char *cmd;
147*7f2fe78bSCy Schubert char **k5users_list;
148*7f2fe78bSCy Schubert char ***k5users_filt_list;
149*7f2fe78bSCy Schubert {
150*7f2fe78bSCy Schubert
151*7f2fe78bSCy Schubert krb5_error_code retval =0;
152*7f2fe78bSCy Schubert krb5_boolean found = FALSE;
153*7f2fe78bSCy Schubert char * out_cmd = NULL;
154*7f2fe78bSCy Schubert unsigned int i=0, j=0, found_count = 0, k=0;
155*7f2fe78bSCy Schubert char ** temp_filt_list;
156*7f2fe78bSCy Schubert
157*7f2fe78bSCy Schubert *k5users_filt_list = NULL;
158*7f2fe78bSCy Schubert
159*7f2fe78bSCy Schubert if (! k5users_list){
160*7f2fe78bSCy Schubert return 0;
161*7f2fe78bSCy Schubert }
162*7f2fe78bSCy Schubert
163*7f2fe78bSCy Schubert while(k5users_list[i]){
164*7f2fe78bSCy Schubert
165*7f2fe78bSCy Schubert retval= k5users_lookup(fp, k5users_list[i], cmd, &found, &out_cmd);
166*7f2fe78bSCy Schubert if (retval)
167*7f2fe78bSCy Schubert return retval;
168*7f2fe78bSCy Schubert
169*7f2fe78bSCy Schubert if (found == FALSE){
170*7f2fe78bSCy Schubert free (k5users_list[i]);
171*7f2fe78bSCy Schubert k5users_list[i] = NULL;
172*7f2fe78bSCy Schubert if (out_cmd) gb_err = out_cmd;
173*7f2fe78bSCy Schubert } else
174*7f2fe78bSCy Schubert found_count ++;
175*7f2fe78bSCy Schubert
176*7f2fe78bSCy Schubert i++;
177*7f2fe78bSCy Schubert }
178*7f2fe78bSCy Schubert
179*7f2fe78bSCy Schubert if (! (temp_filt_list = (char **) calloc(found_count +1, sizeof (char*))))
180*7f2fe78bSCy Schubert return ENOMEM;
181*7f2fe78bSCy Schubert
182*7f2fe78bSCy Schubert for(j= 0, k=0; j < i; j++ ) {
183*7f2fe78bSCy Schubert if (k5users_list[j]){
184*7f2fe78bSCy Schubert temp_filt_list[k] = k5users_list[j];
185*7f2fe78bSCy Schubert k++;
186*7f2fe78bSCy Schubert }
187*7f2fe78bSCy Schubert }
188*7f2fe78bSCy Schubert
189*7f2fe78bSCy Schubert temp_filt_list[k] = NULL;
190*7f2fe78bSCy Schubert
191*7f2fe78bSCy Schubert free (k5users_list);
192*7f2fe78bSCy Schubert
193*7f2fe78bSCy Schubert *k5users_filt_list = temp_filt_list;
194*7f2fe78bSCy Schubert return 0;
195*7f2fe78bSCy Schubert }
196*7f2fe78bSCy Schubert
197*7f2fe78bSCy Schubert krb5_error_code
get_authorized_princ_names(luser,cmd,princ_list)198*7f2fe78bSCy Schubert get_authorized_princ_names(luser, cmd, princ_list)
199*7f2fe78bSCy Schubert const char *luser;
200*7f2fe78bSCy Schubert char *cmd;
201*7f2fe78bSCy Schubert char ***princ_list;
202*7f2fe78bSCy Schubert {
203*7f2fe78bSCy Schubert
204*7f2fe78bSCy Schubert struct passwd *pwd;
205*7f2fe78bSCy Schubert int k5login_flag =0;
206*7f2fe78bSCy Schubert int k5users_flag =0;
207*7f2fe78bSCy Schubert FILE * login_fp = NULL , * users_fp = NULL;
208*7f2fe78bSCy Schubert char ** k5login_list = NULL, ** k5users_list = NULL;
209*7f2fe78bSCy Schubert char ** k5users_filt_list = NULL;
210*7f2fe78bSCy Schubert char ** combined_list = NULL;
211*7f2fe78bSCy Schubert struct stat tb;
212*7f2fe78bSCy Schubert krb5_error_code retval;
213*7f2fe78bSCy Schubert
214*7f2fe78bSCy Schubert *princ_list = NULL;
215*7f2fe78bSCy Schubert
216*7f2fe78bSCy Schubert /* no account => no access */
217*7f2fe78bSCy Schubert
218*7f2fe78bSCy Schubert if ((pwd = getpwnam(luser)) == NULL)
219*7f2fe78bSCy Schubert return 0;
220*7f2fe78bSCy Schubert
221*7f2fe78bSCy Schubert k5login_flag = stat(k5login_path, &tb);
222*7f2fe78bSCy Schubert k5users_flag = stat(k5users_path, &tb);
223*7f2fe78bSCy Schubert
224*7f2fe78bSCy Schubert if (!k5login_flag){
225*7f2fe78bSCy Schubert if ((login_fp = fopen(k5login_path, "r")) == NULL)
226*7f2fe78bSCy Schubert return 0;
227*7f2fe78bSCy Schubert if ( fowner(login_fp, pwd->pw_uid) == FALSE){
228*7f2fe78bSCy Schubert close_time(1 /*k5users_flag*/, (FILE *) 0 /*users_fp*/,
229*7f2fe78bSCy Schubert k5login_flag,login_fp);
230*7f2fe78bSCy Schubert return 0;
231*7f2fe78bSCy Schubert }
232*7f2fe78bSCy Schubert }
233*7f2fe78bSCy Schubert if (!k5users_flag){
234*7f2fe78bSCy Schubert if ((users_fp = fopen(k5users_path, "r")) == NULL)
235*7f2fe78bSCy Schubert return 0;
236*7f2fe78bSCy Schubert
237*7f2fe78bSCy Schubert if ( fowner(users_fp, pwd->pw_uid) == FALSE){
238*7f2fe78bSCy Schubert close_time(k5users_flag,users_fp, k5login_flag,login_fp);
239*7f2fe78bSCy Schubert return 0;
240*7f2fe78bSCy Schubert }
241*7f2fe78bSCy Schubert
242*7f2fe78bSCy Schubert retval = get_all_princ_from_file (users_fp, &k5users_list);
243*7f2fe78bSCy Schubert if(retval) {
244*7f2fe78bSCy Schubert close_time(k5users_flag,users_fp, k5login_flag,login_fp);
245*7f2fe78bSCy Schubert return retval;
246*7f2fe78bSCy Schubert }
247*7f2fe78bSCy Schubert
248*7f2fe78bSCy Schubert rewind(users_fp);
249*7f2fe78bSCy Schubert
250*7f2fe78bSCy Schubert retval = filter(users_fp,cmd, k5users_list, &k5users_filt_list);
251*7f2fe78bSCy Schubert if(retval) {
252*7f2fe78bSCy Schubert close_time(k5users_flag,users_fp, k5login_flag, login_fp);
253*7f2fe78bSCy Schubert return retval;
254*7f2fe78bSCy Schubert }
255*7f2fe78bSCy Schubert }
256*7f2fe78bSCy Schubert
257*7f2fe78bSCy Schubert if (!k5login_flag){
258*7f2fe78bSCy Schubert retval = get_all_princ_from_file (login_fp, &k5login_list);
259*7f2fe78bSCy Schubert if(retval) {
260*7f2fe78bSCy Schubert close_time(k5users_flag,users_fp, k5login_flag,login_fp);
261*7f2fe78bSCy Schubert return retval;
262*7f2fe78bSCy Schubert }
263*7f2fe78bSCy Schubert }
264*7f2fe78bSCy Schubert
265*7f2fe78bSCy Schubert close_time(k5users_flag,users_fp, k5login_flag, login_fp);
266*7f2fe78bSCy Schubert
267*7f2fe78bSCy Schubert retval = list_union(k5login_list, k5users_filt_list, &combined_list);
268*7f2fe78bSCy Schubert if (retval){
269*7f2fe78bSCy Schubert return retval;
270*7f2fe78bSCy Schubert }
271*7f2fe78bSCy Schubert *princ_list = combined_list;
272*7f2fe78bSCy Schubert return 0;
273*7f2fe78bSCy Schubert }
274*7f2fe78bSCy Schubert
close_time(k5users_flag,users_fp,k5login_flag,login_fp)275*7f2fe78bSCy Schubert static void close_time(k5users_flag, users_fp, k5login_flag, login_fp)
276*7f2fe78bSCy Schubert int k5users_flag;
277*7f2fe78bSCy Schubert FILE *users_fp;
278*7f2fe78bSCy Schubert int k5login_flag;
279*7f2fe78bSCy Schubert FILE *login_fp;
280*7f2fe78bSCy Schubert {
281*7f2fe78bSCy Schubert
282*7f2fe78bSCy Schubert if (!k5users_flag) fclose(users_fp);
283*7f2fe78bSCy Schubert if (!k5login_flag) fclose(login_fp);
284*7f2fe78bSCy Schubert
285*7f2fe78bSCy Schubert }
286*7f2fe78bSCy Schubert
find_str_in_list(list,elm)287*7f2fe78bSCy Schubert static krb5_boolean find_str_in_list(list , elm)
288*7f2fe78bSCy Schubert char **list;
289*7f2fe78bSCy Schubert char *elm;
290*7f2fe78bSCy Schubert {
291*7f2fe78bSCy Schubert
292*7f2fe78bSCy Schubert int i=0;
293*7f2fe78bSCy Schubert krb5_boolean found = FALSE;
294*7f2fe78bSCy Schubert
295*7f2fe78bSCy Schubert if (!list) return found;
296*7f2fe78bSCy Schubert
297*7f2fe78bSCy Schubert while (list[i] ){
298*7f2fe78bSCy Schubert if (!strcmp(list[i], elm)){
299*7f2fe78bSCy Schubert found = TRUE;
300*7f2fe78bSCy Schubert break;
301*7f2fe78bSCy Schubert }
302*7f2fe78bSCy Schubert i++;
303*7f2fe78bSCy Schubert }
304*7f2fe78bSCy Schubert
305*7f2fe78bSCy Schubert return found;
306*7f2fe78bSCy Schubert }
307*7f2fe78bSCy Schubert
308*7f2fe78bSCy Schubert /**********************************************************************
309*7f2fe78bSCy Schubert returns the principal that is closes to client (can be the the client
310*7f2fe78bSCy Schubert himself). plist contains
311*7f2fe78bSCy Schubert a principal list obtained from .k5login and .k5users file.
312*7f2fe78bSCy Schubert A principal is picked that has the best chance of getting in.
313*7f2fe78bSCy Schubert
314*7f2fe78bSCy Schubert **********************************************************************/
315*7f2fe78bSCy Schubert
316*7f2fe78bSCy Schubert
get_closest_principal(context,plist,client,found)317*7f2fe78bSCy Schubert krb5_error_code get_closest_principal(context, plist, client, found)
318*7f2fe78bSCy Schubert krb5_context context;
319*7f2fe78bSCy Schubert char **plist;
320*7f2fe78bSCy Schubert krb5_principal *client;
321*7f2fe78bSCy Schubert krb5_boolean *found;
322*7f2fe78bSCy Schubert {
323*7f2fe78bSCy Schubert krb5_error_code retval =0;
324*7f2fe78bSCy Schubert krb5_principal temp_client, best_client = NULL;
325*7f2fe78bSCy Schubert int i = 0, j=0, cnelem, pnelem;
326*7f2fe78bSCy Schubert krb5_boolean got_one;
327*7f2fe78bSCy Schubert
328*7f2fe78bSCy Schubert *found = FALSE;
329*7f2fe78bSCy Schubert
330*7f2fe78bSCy Schubert if (! plist ) return 0;
331*7f2fe78bSCy Schubert
332*7f2fe78bSCy Schubert cnelem = krb5_princ_size(context, *client);
333*7f2fe78bSCy Schubert
334*7f2fe78bSCy Schubert while(plist[i]){
335*7f2fe78bSCy Schubert
336*7f2fe78bSCy Schubert retval = krb5_parse_name(context, plist[i], &temp_client);
337*7f2fe78bSCy Schubert if (retval)
338*7f2fe78bSCy Schubert return retval;
339*7f2fe78bSCy Schubert
340*7f2fe78bSCy Schubert pnelem = krb5_princ_size(context, temp_client);
341*7f2fe78bSCy Schubert
342*7f2fe78bSCy Schubert if ( cnelem > pnelem){
343*7f2fe78bSCy Schubert i++;
344*7f2fe78bSCy Schubert continue;
345*7f2fe78bSCy Schubert }
346*7f2fe78bSCy Schubert
347*7f2fe78bSCy Schubert if (data_eq(*krb5_princ_realm(context, *client),
348*7f2fe78bSCy Schubert *krb5_princ_realm(context, temp_client))) {
349*7f2fe78bSCy Schubert
350*7f2fe78bSCy Schubert got_one = TRUE;
351*7f2fe78bSCy Schubert for(j =0; j < cnelem; j ++){
352*7f2fe78bSCy Schubert krb5_data *p1 =
353*7f2fe78bSCy Schubert krb5_princ_component(context, *client, j);
354*7f2fe78bSCy Schubert krb5_data *p2 =
355*7f2fe78bSCy Schubert krb5_princ_component(context, temp_client, j);
356*7f2fe78bSCy Schubert
357*7f2fe78bSCy Schubert if (!p1 || !p2 || !data_eq(*p1, *p2)) {
358*7f2fe78bSCy Schubert got_one = FALSE;
359*7f2fe78bSCy Schubert break;
360*7f2fe78bSCy Schubert }
361*7f2fe78bSCy Schubert }
362*7f2fe78bSCy Schubert if (got_one == TRUE){
363*7f2fe78bSCy Schubert if(best_client){
364*7f2fe78bSCy Schubert if(krb5_princ_size(context, best_client) >
365*7f2fe78bSCy Schubert krb5_princ_size(context, temp_client)){
366*7f2fe78bSCy Schubert best_client = temp_client;
367*7f2fe78bSCy Schubert }
368*7f2fe78bSCy Schubert }else
369*7f2fe78bSCy Schubert best_client = temp_client;
370*7f2fe78bSCy Schubert }
371*7f2fe78bSCy Schubert }
372*7f2fe78bSCy Schubert i++;
373*7f2fe78bSCy Schubert }
374*7f2fe78bSCy Schubert
375*7f2fe78bSCy Schubert if (best_client) {
376*7f2fe78bSCy Schubert *found = TRUE;
377*7f2fe78bSCy Schubert *client = best_client;
378*7f2fe78bSCy Schubert }
379*7f2fe78bSCy Schubert
380*7f2fe78bSCy Schubert return 0;
381*7f2fe78bSCy Schubert }
382*7f2fe78bSCy Schubert
383*7f2fe78bSCy Schubert /****************************************************************
384*7f2fe78bSCy Schubert find_either_ticket checks to see whether there is a ticket for the
385*7f2fe78bSCy Schubert end server or tgt, if neither is there the return FALSE,
386*7f2fe78bSCy Schubert *****************************************************************/
387*7f2fe78bSCy Schubert
find_either_ticket(context,cc,client,end_server,found)388*7f2fe78bSCy Schubert krb5_error_code find_either_ticket (context, cc, client, end_server, found)
389*7f2fe78bSCy Schubert krb5_context context;
390*7f2fe78bSCy Schubert krb5_ccache cc;
391*7f2fe78bSCy Schubert krb5_principal client;
392*7f2fe78bSCy Schubert krb5_principal end_server;
393*7f2fe78bSCy Schubert krb5_boolean *found;
394*7f2fe78bSCy Schubert {
395*7f2fe78bSCy Schubert
396*7f2fe78bSCy Schubert krb5_principal kdc_server;
397*7f2fe78bSCy Schubert krb5_error_code retval;
398*7f2fe78bSCy Schubert krb5_boolean temp_found = FALSE;
399*7f2fe78bSCy Schubert
400*7f2fe78bSCy Schubert if (ks_ccache_is_initialized(context, cc)) {
401*7f2fe78bSCy Schubert
402*7f2fe78bSCy Schubert retval = find_ticket(context, cc, client, end_server, &temp_found);
403*7f2fe78bSCy Schubert if (retval)
404*7f2fe78bSCy Schubert return retval;
405*7f2fe78bSCy Schubert
406*7f2fe78bSCy Schubert if (temp_found == FALSE){
407*7f2fe78bSCy Schubert retval = ksu_tgtname(context,
408*7f2fe78bSCy Schubert krb5_princ_realm(context, client),
409*7f2fe78bSCy Schubert krb5_princ_realm(context, client),
410*7f2fe78bSCy Schubert &kdc_server);
411*7f2fe78bSCy Schubert if (retval)
412*7f2fe78bSCy Schubert return retval;
413*7f2fe78bSCy Schubert
414*7f2fe78bSCy Schubert retval = find_ticket(context, cc,client, kdc_server, &temp_found);
415*7f2fe78bSCy Schubert if(retval)
416*7f2fe78bSCy Schubert return retval;
417*7f2fe78bSCy Schubert }
418*7f2fe78bSCy Schubert else if (auth_debug)
419*7f2fe78bSCy Schubert printf("find_either_ticket: found end server ticket\n");
420*7f2fe78bSCy Schubert }
421*7f2fe78bSCy Schubert
422*7f2fe78bSCy Schubert *found = temp_found;
423*7f2fe78bSCy Schubert
424*7f2fe78bSCy Schubert return 0;
425*7f2fe78bSCy Schubert }
426*7f2fe78bSCy Schubert
427*7f2fe78bSCy Schubert
find_ticket(context,cc,client,server,found)428*7f2fe78bSCy Schubert krb5_error_code find_ticket (context, cc, client, server, found)
429*7f2fe78bSCy Schubert krb5_context context;
430*7f2fe78bSCy Schubert krb5_ccache cc;
431*7f2fe78bSCy Schubert krb5_principal client;
432*7f2fe78bSCy Schubert krb5_principal server;
433*7f2fe78bSCy Schubert krb5_boolean *found;
434*7f2fe78bSCy Schubert {
435*7f2fe78bSCy Schubert
436*7f2fe78bSCy Schubert krb5_creds tgt, tgtq;
437*7f2fe78bSCy Schubert krb5_error_code retval;
438*7f2fe78bSCy Schubert
439*7f2fe78bSCy Schubert *found = FALSE;
440*7f2fe78bSCy Schubert
441*7f2fe78bSCy Schubert memset(&tgtq, 0, sizeof(tgtq));
442*7f2fe78bSCy Schubert memset(&tgt, 0, sizeof(tgt));
443*7f2fe78bSCy Schubert
444*7f2fe78bSCy Schubert retval= krb5_copy_principal(context, client, &tgtq.client);
445*7f2fe78bSCy Schubert if (retval)
446*7f2fe78bSCy Schubert return retval;
447*7f2fe78bSCy Schubert
448*7f2fe78bSCy Schubert retval= krb5_copy_principal(context, server, &tgtq.server);
449*7f2fe78bSCy Schubert if (retval)
450*7f2fe78bSCy Schubert return retval ;
451*7f2fe78bSCy Schubert
452*7f2fe78bSCy Schubert retval = krb5_cc_retrieve_cred(context, cc, KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES,
453*7f2fe78bSCy Schubert &tgtq, &tgt);
454*7f2fe78bSCy Schubert
455*7f2fe78bSCy Schubert if (! retval) retval = krb5_check_exp(context, tgt.times);
456*7f2fe78bSCy Schubert
457*7f2fe78bSCy Schubert if (retval){
458*7f2fe78bSCy Schubert if ((retval != KRB5_CC_NOTFOUND) &&
459*7f2fe78bSCy Schubert (retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){
460*7f2fe78bSCy Schubert return retval ;
461*7f2fe78bSCy Schubert }
462*7f2fe78bSCy Schubert } else{
463*7f2fe78bSCy Schubert *found = TRUE;
464*7f2fe78bSCy Schubert return 0;
465*7f2fe78bSCy Schubert }
466*7f2fe78bSCy Schubert
467*7f2fe78bSCy Schubert free(tgtq.server);
468*7f2fe78bSCy Schubert free(tgtq.client);
469*7f2fe78bSCy Schubert
470*7f2fe78bSCy Schubert return 0;
471*7f2fe78bSCy Schubert }
472*7f2fe78bSCy Schubert
473*7f2fe78bSCy Schubert
474*7f2fe78bSCy Schubert
find_princ_in_list(context,princ,plist,found)475*7f2fe78bSCy Schubert krb5_error_code find_princ_in_list (context, princ, plist, found)
476*7f2fe78bSCy Schubert krb5_context context;
477*7f2fe78bSCy Schubert krb5_principal princ;
478*7f2fe78bSCy Schubert char **plist;
479*7f2fe78bSCy Schubert krb5_boolean *found;
480*7f2fe78bSCy Schubert {
481*7f2fe78bSCy Schubert
482*7f2fe78bSCy Schubert int i=0;
483*7f2fe78bSCy Schubert char * princname;
484*7f2fe78bSCy Schubert krb5_error_code retval;
485*7f2fe78bSCy Schubert
486*7f2fe78bSCy Schubert *found = FALSE;
487*7f2fe78bSCy Schubert
488*7f2fe78bSCy Schubert if (!plist) return 0;
489*7f2fe78bSCy Schubert
490*7f2fe78bSCy Schubert retval = krb5_unparse_name(context, princ, &princname);
491*7f2fe78bSCy Schubert if (retval)
492*7f2fe78bSCy Schubert return retval;
493*7f2fe78bSCy Schubert
494*7f2fe78bSCy Schubert while (plist[i] ){
495*7f2fe78bSCy Schubert if (!strcmp(plist[i], princname)){
496*7f2fe78bSCy Schubert *found = TRUE;
497*7f2fe78bSCy Schubert break;
498*7f2fe78bSCy Schubert }
499*7f2fe78bSCy Schubert i++;
500*7f2fe78bSCy Schubert }
501*7f2fe78bSCy Schubert
502*7f2fe78bSCy Schubert return 0;
503*7f2fe78bSCy Schubert
504*7f2fe78bSCy Schubert }
505*7f2fe78bSCy Schubert
506*7f2fe78bSCy Schubert typedef struct princ_info {
507*7f2fe78bSCy Schubert krb5_principal p;
508*7f2fe78bSCy Schubert krb5_boolean found;
509*7f2fe78bSCy Schubert }princ_info;
510*7f2fe78bSCy Schubert
511*7f2fe78bSCy Schubert /**********************************************************************
512*7f2fe78bSCy Schubert get_best_princ_for_target -
513*7f2fe78bSCy Schubert
514*7f2fe78bSCy Schubert sets the client name, path_out gets set, if authorization is not possible
515*7f2fe78bSCy Schubert path_out gets set to ...
516*7f2fe78bSCy Schubert
517*7f2fe78bSCy Schubert ***********************************************************************/
518*7f2fe78bSCy Schubert
get_best_princ_for_target(context,source_uid,target_uid,source_user,target_user,cc_source,options,cmd,hostname,client,path_out)519*7f2fe78bSCy Schubert krb5_error_code get_best_princ_for_target(context, source_uid, target_uid,
520*7f2fe78bSCy Schubert source_user, target_user,
521*7f2fe78bSCy Schubert cc_source, options, cmd,
522*7f2fe78bSCy Schubert hostname, client, path_out)
523*7f2fe78bSCy Schubert krb5_context context;
524*7f2fe78bSCy Schubert uid_t source_uid;
525*7f2fe78bSCy Schubert uid_t target_uid;
526*7f2fe78bSCy Schubert char *source_user;
527*7f2fe78bSCy Schubert char *target_user;
528*7f2fe78bSCy Schubert krb5_ccache cc_source;
529*7f2fe78bSCy Schubert krb5_get_init_creds_opt *options;
530*7f2fe78bSCy Schubert char *cmd;
531*7f2fe78bSCy Schubert char *hostname;
532*7f2fe78bSCy Schubert krb5_principal *client;
533*7f2fe78bSCy Schubert int *path_out;
534*7f2fe78bSCy Schubert {
535*7f2fe78bSCy Schubert
536*7f2fe78bSCy Schubert princ_info princ_trials[10];
537*7f2fe78bSCy Schubert krb5_principal cc_def_princ = NULL;
538*7f2fe78bSCy Schubert krb5_principal temp_client;
539*7f2fe78bSCy Schubert krb5_principal target_client;
540*7f2fe78bSCy Schubert krb5_principal source_client;
541*7f2fe78bSCy Schubert krb5_principal end_server;
542*7f2fe78bSCy Schubert krb5_error_code retval;
543*7f2fe78bSCy Schubert char ** aplist =NULL;
544*7f2fe78bSCy Schubert krb5_boolean found = FALSE;
545*7f2fe78bSCy Schubert struct stat tb;
546*7f2fe78bSCy Schubert int count =0;
547*7f2fe78bSCy Schubert int i;
548*7f2fe78bSCy Schubert
549*7f2fe78bSCy Schubert *path_out = 0;
550*7f2fe78bSCy Schubert
551*7f2fe78bSCy Schubert /* -n option was specified client is set we are done */
552*7f2fe78bSCy Schubert if (*client != NULL)
553*7f2fe78bSCy Schubert return 0;
554*7f2fe78bSCy Schubert
555*7f2fe78bSCy Schubert if (ks_ccache_is_initialized(context, cc_source)) {
556*7f2fe78bSCy Schubert retval = krb5_cc_get_principal(context, cc_source, &cc_def_princ);
557*7f2fe78bSCy Schubert if (retval)
558*7f2fe78bSCy Schubert return retval;
559*7f2fe78bSCy Schubert }
560*7f2fe78bSCy Schubert
561*7f2fe78bSCy Schubert retval=krb5_parse_name(context, target_user, &target_client);
562*7f2fe78bSCy Schubert if (retval)
563*7f2fe78bSCy Schubert return retval;
564*7f2fe78bSCy Schubert
565*7f2fe78bSCy Schubert retval=krb5_parse_name(context, source_user, &source_client);
566*7f2fe78bSCy Schubert if (retval)
567*7f2fe78bSCy Schubert return retval;
568*7f2fe78bSCy Schubert
569*7f2fe78bSCy Schubert if (source_uid == 0){
570*7f2fe78bSCy Schubert if (target_uid != 0)
571*7f2fe78bSCy Schubert *client = target_client; /* this will be used to restrict
572*7f2fe78bSCy Schubert the cache copty */
573*7f2fe78bSCy Schubert else {
574*7f2fe78bSCy Schubert if(cc_def_princ)
575*7f2fe78bSCy Schubert *client = cc_def_princ;
576*7f2fe78bSCy Schubert else
577*7f2fe78bSCy Schubert *client = target_client;
578*7f2fe78bSCy Schubert }
579*7f2fe78bSCy Schubert
580*7f2fe78bSCy Schubert if (auth_debug)
581*7f2fe78bSCy Schubert printf(" GET_best_princ_for_target: via source_uid == 0\n");
582*7f2fe78bSCy Schubert
583*7f2fe78bSCy Schubert return 0;
584*7f2fe78bSCy Schubert }
585*7f2fe78bSCy Schubert
586*7f2fe78bSCy Schubert /* from here on, the code is for source_uid != 0 */
587*7f2fe78bSCy Schubert
588*7f2fe78bSCy Schubert if (source_uid && (source_uid == target_uid)){
589*7f2fe78bSCy Schubert if(cc_def_princ)
590*7f2fe78bSCy Schubert *client = cc_def_princ;
591*7f2fe78bSCy Schubert else
592*7f2fe78bSCy Schubert *client = target_client;
593*7f2fe78bSCy Schubert if (auth_debug)
594*7f2fe78bSCy Schubert printf("GET_best_princ_for_target: via source_uid == target_uid\n");
595*7f2fe78bSCy Schubert return 0;
596*7f2fe78bSCy Schubert }
597*7f2fe78bSCy Schubert
598*7f2fe78bSCy Schubert /* Become root, then target for looking at .k5login.*/
599*7f2fe78bSCy Schubert if (krb5_seteuid(0) || krb5_seteuid(target_uid) ) {
600*7f2fe78bSCy Schubert return errno;
601*7f2fe78bSCy Schubert }
602*7f2fe78bSCy Schubert
603*7f2fe78bSCy Schubert /* if .k5users and .k5login do not exist */
604*7f2fe78bSCy Schubert if (stat(k5login_path, &tb) && stat(k5users_path, &tb) ){
605*7f2fe78bSCy Schubert *client = target_client;
606*7f2fe78bSCy Schubert
607*7f2fe78bSCy Schubert if (cmd)
608*7f2fe78bSCy Schubert *path_out = NOT_AUTHORIZED;
609*7f2fe78bSCy Schubert
610*7f2fe78bSCy Schubert if (auth_debug)
611*7f2fe78bSCy Schubert printf(" GET_best_princ_for_target: via no auth files path\n");
612*7f2fe78bSCy Schubert
613*7f2fe78bSCy Schubert return 0;
614*7f2fe78bSCy Schubert }else{
615*7f2fe78bSCy Schubert retval = get_authorized_princ_names(target_user, cmd, &aplist);
616*7f2fe78bSCy Schubert if (retval)
617*7f2fe78bSCy Schubert return retval;
618*7f2fe78bSCy Schubert
619*7f2fe78bSCy Schubert /* .k5users or .k5login exist, but no authorization */
620*7f2fe78bSCy Schubert if ((!aplist) || (!aplist[0])) {
621*7f2fe78bSCy Schubert *path_out = NOT_AUTHORIZED;
622*7f2fe78bSCy Schubert if (auth_debug)
623*7f2fe78bSCy Schubert printf("GET_best_princ_for_target: via empty auth files path\n");
624*7f2fe78bSCy Schubert return 0;
625*7f2fe78bSCy Schubert }
626*7f2fe78bSCy Schubert }
627*7f2fe78bSCy Schubert
628*7f2fe78bSCy Schubert retval = krb5_sname_to_principal(context, hostname, NULL,
629*7f2fe78bSCy Schubert KRB5_NT_SRV_HST, &end_server);
630*7f2fe78bSCy Schubert if (retval)
631*7f2fe78bSCy Schubert return retval;
632*7f2fe78bSCy Schubert
633*7f2fe78bSCy Schubert
634*7f2fe78bSCy Schubert /* first see if default principal of the source cache
635*7f2fe78bSCy Schubert * can get us in, then the target_user@realm, then the
636*7f2fe78bSCy Schubert * source_user@realm. If all of them fail, try any
637*7f2fe78bSCy Schubert * other ticket in the cache. */
638*7f2fe78bSCy Schubert
639*7f2fe78bSCy Schubert if (cc_def_princ)
640*7f2fe78bSCy Schubert princ_trials[count ++].p = cc_def_princ;
641*7f2fe78bSCy Schubert else
642*7f2fe78bSCy Schubert princ_trials[count ++].p = NULL;
643*7f2fe78bSCy Schubert
644*7f2fe78bSCy Schubert princ_trials[count ++].p = target_client;
645*7f2fe78bSCy Schubert princ_trials[count ++].p = source_client;
646*7f2fe78bSCy Schubert
647*7f2fe78bSCy Schubert for (i= 0; i < count; i ++)
648*7f2fe78bSCy Schubert princ_trials[i].found = FALSE;
649*7f2fe78bSCy Schubert
650*7f2fe78bSCy Schubert for (i= 0; i < count; i ++){
651*7f2fe78bSCy Schubert if(princ_trials[i].p) {
652*7f2fe78bSCy Schubert retval= find_princ_in_list(context, princ_trials[i].p, aplist,
653*7f2fe78bSCy Schubert &found);
654*7f2fe78bSCy Schubert if (retval)
655*7f2fe78bSCy Schubert return retval;
656*7f2fe78bSCy Schubert
657*7f2fe78bSCy Schubert if (found == TRUE){
658*7f2fe78bSCy Schubert princ_trials[i].found = TRUE;
659*7f2fe78bSCy Schubert
660*7f2fe78bSCy Schubert retval = find_either_ticket (context, cc_source,
661*7f2fe78bSCy Schubert princ_trials[i].p,
662*7f2fe78bSCy Schubert end_server, &found);
663*7f2fe78bSCy Schubert if (retval)
664*7f2fe78bSCy Schubert return retval;
665*7f2fe78bSCy Schubert if (found == TRUE){
666*7f2fe78bSCy Schubert *client = princ_trials[i].p;
667*7f2fe78bSCy Schubert if (auth_debug)
668*7f2fe78bSCy Schubert printf("GET_best_princ_for_target: via ticket file, choice #%d\n", i);
669*7f2fe78bSCy Schubert return 0;
670*7f2fe78bSCy Schubert }
671*7f2fe78bSCy Schubert }
672*7f2fe78bSCy Schubert }
673*7f2fe78bSCy Schubert }
674*7f2fe78bSCy Schubert
675*7f2fe78bSCy Schubert /* out of preferred principals, see if there is any ticket that will
676*7f2fe78bSCy Schubert get us in */
677*7f2fe78bSCy Schubert
678*7f2fe78bSCy Schubert i=0;
679*7f2fe78bSCy Schubert while (aplist[i]){
680*7f2fe78bSCy Schubert retval = krb5_parse_name(context, aplist[i], &temp_client);
681*7f2fe78bSCy Schubert if (retval)
682*7f2fe78bSCy Schubert return retval;
683*7f2fe78bSCy Schubert
684*7f2fe78bSCy Schubert retval = find_either_ticket (context, cc_source, temp_client,
685*7f2fe78bSCy Schubert end_server, &found);
686*7f2fe78bSCy Schubert if (retval)
687*7f2fe78bSCy Schubert return retval;
688*7f2fe78bSCy Schubert
689*7f2fe78bSCy Schubert if (found == TRUE){
690*7f2fe78bSCy Schubert if (auth_debug)
691*7f2fe78bSCy Schubert printf("GET_best_princ_for_target: via ticket file, choice: any ok ticket \n" );
692*7f2fe78bSCy Schubert *client = temp_client;
693*7f2fe78bSCy Schubert return 0;
694*7f2fe78bSCy Schubert }
695*7f2fe78bSCy Schubert
696*7f2fe78bSCy Schubert krb5_free_principal(context, temp_client);
697*7f2fe78bSCy Schubert
698*7f2fe78bSCy Schubert i++;
699*7f2fe78bSCy Schubert }
700*7f2fe78bSCy Schubert
701*7f2fe78bSCy Schubert /* no tickets qualified, select a principal, that may be used
702*7f2fe78bSCy Schubert for password promting */
703*7f2fe78bSCy Schubert
704*7f2fe78bSCy Schubert
705*7f2fe78bSCy Schubert for (i=0; i < count; i ++){
706*7f2fe78bSCy Schubert if (princ_trials[i].found == TRUE){
707*7f2fe78bSCy Schubert *client = princ_trials[i].p;
708*7f2fe78bSCy Schubert
709*7f2fe78bSCy Schubert if (auth_debug)
710*7f2fe78bSCy Schubert printf("GET_best_princ_for_target: via prompt passwd list choice #%d \n",i);
711*7f2fe78bSCy Schubert return 0;
712*7f2fe78bSCy Schubert }
713*7f2fe78bSCy Schubert }
714*7f2fe78bSCy Schubert
715*7f2fe78bSCy Schubert #ifdef PRINC_LOOK_AHEAD
716*7f2fe78bSCy Schubert for (i=0; i < count; i ++){
717*7f2fe78bSCy Schubert if (princ_trials[i].p){
718*7f2fe78bSCy Schubert retval=krb5_copy_principal(context, princ_trials[i].p,
719*7f2fe78bSCy Schubert &temp_client);
720*7f2fe78bSCy Schubert if(retval)
721*7f2fe78bSCy Schubert return retval;
722*7f2fe78bSCy Schubert
723*7f2fe78bSCy Schubert /* get the client name that is the closest
724*7f2fe78bSCy Schubert to the three princ in trials */
725*7f2fe78bSCy Schubert
726*7f2fe78bSCy Schubert retval=get_closest_principal(context, aplist, &temp_client,
727*7f2fe78bSCy Schubert &found);
728*7f2fe78bSCy Schubert if(retval)
729*7f2fe78bSCy Schubert return retval;
730*7f2fe78bSCy Schubert
731*7f2fe78bSCy Schubert if (found == TRUE){
732*7f2fe78bSCy Schubert *client = temp_client;
733*7f2fe78bSCy Schubert if (auth_debug)
734*7f2fe78bSCy Schubert printf("GET_best_princ_for_target: via prompt passwd list choice: approximation of princ in trials # %d \n",i);
735*7f2fe78bSCy Schubert return 0;
736*7f2fe78bSCy Schubert }
737*7f2fe78bSCy Schubert krb5_free_principal(context, temp_client);
738*7f2fe78bSCy Schubert }
739*7f2fe78bSCy Schubert }
740*7f2fe78bSCy Schubert
741*7f2fe78bSCy Schubert #endif /* PRINC_LOOK_AHEAD */
742*7f2fe78bSCy Schubert
743*7f2fe78bSCy Schubert
744*7f2fe78bSCy Schubert if(auth_debug)
745*7f2fe78bSCy Schubert printf( "GET_best_princ_for_target: out of luck, can't get appropriate default principal\n");
746*7f2fe78bSCy Schubert
747*7f2fe78bSCy Schubert *path_out = NOT_AUTHORIZED;
748*7f2fe78bSCy Schubert return 0;
749*7f2fe78bSCy Schubert }
750