source: trunk/athena/bin/grenew/grenew.c @ 20509

Revision 20509, 8.7 KB checked in by ghudson, 20 years ago (diff)
Don't set the grenew windows GTK_WINDOW_POPUP; that means they don't get focus under sawfish, and thus you can't type in a password.
Line 
1/* Renew a credentials cache using a graphical interface. Much of the source
2 * is modified from that of kinit.
3 *
4 * $Id: grenew.c,v 1.6 2004-05-27 18:38:46 ghudson Exp $
5 */
6
7#include <gtk/gtk.h>
8#include <krb5.h>
9#include <kerberosIV/krb.h>
10#include <string.h>
11#include <stdio.h>
12#include <com_err.h>
13
14char *progname = NULL;
15const char *name = NULL;
16
17static void quit();
18static void do_error_dialog(char *msg);
19static void do_fatal_dialog(char *msg);
20static void do_renew(GtkWidget *widget, GtkWidget *entry);
21static void dialog_response_cb(GtkWidget *w, gint response, GtkWidget *entry);
22static void create_window();
23int try_krb4(krb5_context kcontext, krb5_principal me, char *password,
24             krb5_deltat lifetime);
25int try_convert524(krb5_context kcontext, krb5_ccache ccache);
26
27/* library functions not declared inside the included headers. */
28void krb524_init_ets(krb5_context kcontext);
29int krb524_convert_creds_kdc(krb5_context kcontext,
30                             krb5_creds * k5creds,
31                             CREDENTIALS * k4creds);
32
33static void quit()
34{
35  exit(0);
36}
37
38static void do_error_dialog(char *msg)
39{
40  static GtkWidget *window = NULL;
41
42  if (window)
43    gtk_widget_destroy(window);
44  window = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_WARNING,
45                                  GTK_BUTTONS_OK, msg);
46  g_signal_connect(G_OBJECT(window), "response",
47                   G_CALLBACK(gtk_widget_destroy), NULL);
48  g_signal_connect(G_OBJECT(window), "destroy",
49                   G_CALLBACK(gtk_widget_destroyed), &window);
50  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
51  gtk_widget_show(window);
52}
53
54static void do_fatal_dialog(char *msg)
55{
56  GtkWidget *window;
57
58  msg = g_strdup_printf("Fatal Error:\n\n%s", msg);
59  window = gtk_message_dialog_new(NULL,
60                                  GTK_DIALOG_MODAL,
61                                  GTK_MESSAGE_ERROR,
62                                  GTK_BUTTONS_OK, msg);
63  g_signal_connect(G_OBJECT(window), "response",
64                   G_CALLBACK(quit), NULL);
65  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
66  gtk_widget_show(window);
67}
68
69static void do_renew(GtkWidget *widget, GtkWidget *entry)
70{
71  char *pass;
72  krb5_error_code code;
73  krb5_context kcontext;
74  krb5_principal me = NULL;
75  char *service_name = NULL;
76  krb5_ccache ccache = NULL;
77  krb5_creds my_creds;
78  char *msg = NULL;
79  krb5_deltat start_time = 0;
80  krb5_deltat lifetime = 10 * 60 * 60;
81  krb5_get_init_creds_opt opts;
82  int non_fatal = 0;
83
84  pass = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
85  gtk_entry_set_text(GTK_ENTRY(entry), "");
86
87  krb5_get_init_creds_opt_init(&opts);
88
89  if (!pass || !strlen(pass))
90    {
91      non_fatal = 1;
92      msg = g_strdup("Incorrect password: please try again.");
93    }
94  else if ((code = krb5_init_context(&kcontext)))
95    msg = g_strdup_printf("%s when initializing kerberos library",
96                          error_message(code));
97  else if ((code = krb5_cc_default(kcontext, &ccache)))
98    msg = g_strdup_printf("%s while getting default cache.",
99                          error_message(code));
100  else if ((code = krb5_parse_name(kcontext, name, &me)))
101    msg = g_strdup_printf("%s while parsing name %s.", error_message(code),
102                          name);
103  else if ((code = krb5_get_init_creds_password(kcontext,
104                                                &my_creds, me, pass,
105                                                krb5_prompter_posix, NULL,
106                                                start_time, service_name,
107                                                &opts)))
108    {
109      if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
110        {
111          non_fatal = 1;
112          msg = g_strdup("Incorrect password: please try again.");
113        }
114      else
115        {
116          msg = g_strdup_printf("%s while getting initial"
117                                " credentials", error_message(code));
118        }
119    }
120  else
121    {
122      int got_krb4 = try_krb4(kcontext, me, pass, lifetime);
123      if ((code = krb5_cc_initialize(kcontext, ccache, me)))
124        {
125          msg = g_strdup_printf("%s while initializing cache",
126                                error_message(code));
127        }
128      else if ((code = krb5_cc_store_cred(kcontext, ccache,
129                                          &my_creds)))
130        {
131          msg = g_strdup_printf("%s while storing credentials",
132                                error_message(code));
133        }
134      else
135        {
136          if (!got_krb4)
137            try_convert524(kcontext, ccache);
138          if (me)
139            krb5_free_principal(kcontext, me);
140          if (ccache)
141            krb5_cc_close(kcontext, ccache);
142
143          krb5_free_context(kcontext);
144        }
145    }
146
147  g_free(pass);
148
149  if (msg)
150    {
151      /* encountered an error. don't quit */
152      if (non_fatal)
153        do_error_dialog(msg);
154      else
155        do_fatal_dialog(msg);
156      g_free(msg);
157    }
158  else
159    /* no errors, we're done */
160    {
161      system("fsid -a > /dev/null");
162      system("zctl load /dev/null > /dev/null");
163      exit(0);
164    }
165}
166
167static void dialog_response_cb(GtkWidget *w, gint response, GtkWidget *entry)
168{
169  gtk_widget_grab_focus(GTK_WIDGET(entry));
170
171  if (response == GTK_RESPONSE_OK)
172    do_renew(w, entry);
173  else
174    quit();
175}
176
177static void create_window()
178{
179  GtkWidget *window;
180  GtkWidget *label;
181  GtkWidget *entry;
182  GtkWidget *button;
183
184  window = gtk_dialog_new_with_buttons("Renewing authentication",
185                                       NULL, 0,
186                                       GTK_STOCK_OK,
187                                       GTK_RESPONSE_OK,
188                                       GTK_STOCK_CANCEL,
189                                       GTK_RESPONSE_CANCEL,
190                                       NULL);
191
192  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
193
194  label = gtk_label_new("Type your password now to renew your authentication "
195                        "to the system, which expires every 10 hours.");
196  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
197  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
198  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), label, TRUE, TRUE, 0);
199  gtk_widget_show(label);
200
201  entry = gtk_entry_new();
202  gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
203  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), entry, TRUE, TRUE, 0);
204  gtk_widget_grab_focus(entry);
205  gtk_widget_show(entry);
206
207  g_signal_connect_object(G_OBJECT(entry), "activate",
208                          G_CALLBACK(do_renew), entry, 0);
209  g_signal_connect_object(G_OBJECT(window), "response",
210                          G_CALLBACK(dialog_response_cb), entry, 0);
211  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(quit), NULL);
212
213  gtk_widget_show(window);
214}
215
216/* This function is from kinit. */
217int try_krb4(kcontext, me, password, lifetime)
218        krb5_context kcontext;
219        krb5_principal me;
220        char *password;
221        krb5_deltat lifetime;
222{
223        krb5_error_code code;
224        int krbval;
225        char v4name[ANAME_SZ], v4inst[INST_SZ], v4realm[REALM_SZ];
226        int v4life;
227
228        /* Translate to a Kerberos 4 principal. */
229        code = krb5_524_conv_principal(kcontext, me, v4name, v4inst, v4realm);
230        if (code)
231                return(code);
232
233        v4life = lifetime / (5 * 60);
234        if (v4life < 1)
235                v4life = 1;
236        if (v4life > 255)
237                v4life = 255;
238
239        krbval = krb_get_pw_in_tkt(v4name, v4inst, v4realm, "krbtgt", v4realm,
240                                           v4life, password);
241
242        if (krbval != INTK_OK) {
243                fprintf(stderr, "Kerberos 4 error: %s\n",
244                        krb_get_err_text(krbval));
245                return 0;
246        }
247        return 1;
248}
249
250/* Convert krb5 tickets to krb4. This function was copied from kinit */
251int try_convert524(kcontext, ccache)
252         krb5_context kcontext;
253         krb5_ccache ccache;
254{
255        krb5_principal me, kpcserver;
256        krb5_error_code kpccode;
257        int kpcval;
258        krb5_creds increds, *v5creds;
259        CREDENTIALS v4creds;
260
261        /* or do this directly with krb524_convert_creds_kdc */
262        krb524_init_ets(kcontext);
263
264        if ((kpccode = krb5_cc_get_principal(kcontext, ccache, &me))) {
265                com_err(progname, kpccode, "while getting principal name");
266                return 0;
267        }
268
269        /* cc->ccache, already set up */
270        /* client->me, already set up */
271        if ((kpccode = krb5_build_principal(kcontext,
272                                                    &kpcserver,
273                                                    krb5_princ_realm(kcontext, me)->length,
274                                                    krb5_princ_realm(kcontext, me)->data,
275                                                    "krbtgt",
276                                                    krb5_princ_realm(kcontext, me)->data,
277                                                NULL))) {
278          com_err(progname, kpccode,
279                          "while creating service principal name");
280          return 0;
281        }
282
283        memset((char *) &increds, 0, sizeof(increds));
284        increds.client = me;
285        increds.server = kpcserver;
286        increds.times.endtime = 0;
287        increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
288        if ((kpccode = krb5_get_credentials(kcontext, 0,
289                                                ccache,
290                                                &increds,
291                                                &v5creds))) {
292                com_err(progname, kpccode,
293                        "getting V5 credentials");
294                return 0;
295        }
296        if ((kpccode = krb524_convert_creds_kdc(kcontext,
297                                                        v5creds,
298                                                        &v4creds))) {
299                com_err(progname, kpccode,
300                        "converting to V4 credentials");
301                return 0;
302        }
303        /* this is stolen from the v4 kinit */
304        /* initialize ticket cache */
305        if ((kpcval = in_tkt(v4creds.pname,v4creds.pinst)
306                 != KSUCCESS)) {
307                com_err(progname, kpcval,
308                        "trying to create the V4 ticket file");
309                return 0;
310        }
311        /* stash ticket, session key, etc. for future use */
312        if ((kpcval = krb_save_credentials(v4creds.service,
313                                                   v4creds.instance,
314                                                   v4creds.realm,
315                                                   v4creds.session,
316                                                   v4creds.lifetime,
317                                                   v4creds.kvno,
318                                                   &(v4creds.ticket_st),
319                                                   v4creds.issue_date))) {
320                com_err(progname, kpcval,
321                        "trying to save the V4 ticket");
322                return 0;
323        }
324        return 1;
325}
326
327int main(int argc, char **argv)
328{
329  gtk_init(&argc, &argv);
330
331  progname = g_get_prgname();
332  if (argc > 1)
333    name = argv[1];
334  else
335    name = g_get_user_name();
336  create_window();
337  gtk_main();
338  return 0;
339}
Note: See TracBrowser for help on using the repository browser.