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
krb5_auth_check(context,client_pname,hostname,options,target_user,cc,path_passwd,target_uid)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
ksu_get_tgt_via_passwd(context,client,options,zero_password,creds_out)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
dump_principal(context,str,p)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
plain_dump_principal(context,p)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
get_best_principal(context,plist,client)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