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

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