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
krb5_auth_check(krb5_context context,krb5_principal client_pname,char * hostname,krb5_get_init_creds_opt * options,char * target_user,krb5_ccache cc,int * path_passwd,uid_t target_uid)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
ksu_get_tgt_via_passwd(krb5_context context,krb5_principal client,krb5_get_init_creds_opt * options,krb5_boolean * zero_password,krb5_creds * creds_out)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
dump_principal(krb5_context context,char * str,krb5_principal p)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
plain_dump_principal(krb5_context context,krb5_principal p)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