1 /* kpasswd.c --- verify kerberos passwords.
2 * written by Nat Lanza (magus@cs.cmu.edu) for
3 * xscreensaver, Copyright (c) 1993-1997, 1998 Jamie Zawinski <jwz@jwz.org>
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation. No representations are made about the suitability of this
10 * software for any purpose. It is provided "as is" without express or
18 #ifndef NO_LOCKING /* whole file */
27 #include <sys/types.h>
31 #if !defined(VMS) && !defined(HAVE_ADJUNCT_PASSWD)
37 # include <sys/param.h>
38 # if _BSDI_VERSION >= 199608
51 /* The user information we need to store */
52 static char realm[REALM_SZ];
53 static char name[ANAME_SZ];
54 static char inst[INST_SZ];
58 /* Called at startup to grab user, instance, and realm information
59 from the user's ticketfile (remember, name.inst@realm). Since we're
60 using tf_get_pname(), this should work even if your kerberos username
61 isn't the same as your local username. We grab the ticket at startup
62 time so that even if your ticketfile dies while the screen's locked
63 we'll still have the information to unlock it.
65 Problems: the password dialog currently displays local username, so if
66 you have some non-standard name/instance when you run xscreensaver,
67 you'll need to remember what it was when unlocking, or else you lose.
69 Also, we use des_string_to_key(), so if you have an AFS password
70 (encrypted with ka_StringToKey()), you'll lose. Get a kerberos password;
73 Like the original lock_init, we return false if something went wrong.
74 We don't use the arguments we're given, though.
77 kerberos_lock_init (int argc, char **argv, Bool verbose_p)
81 memset(name, 0, sizeof(name));
82 memset(inst, 0, sizeof(inst));
84 /* find out where the user's keeping his tickets.
85 squirrel it away for later use. */
86 tk_file = tkt_string();
88 /* open ticket file or die trying. */
89 if ((k_errno = tf_init(tk_file, R_TKT_FIL))) {
93 /* same with principal and instance names */
94 if ((k_errno = tf_get_pname(name)) ||
95 (k_errno = tf_get_pinst(inst))) {
99 /* close the ticketfile to release the lock on it. */
102 /* figure out what realm we're authenticated to. this ought
103 to be the local realm, but it pays to be sure. */
104 if ((k_errno = krb_get_tf_realm(tk_file, realm))) {
108 /* last-minute sanity check on what we got. */
109 if ((strlen(name)+strlen(inst)+strlen(realm)+3) >
110 (REALM_SZ + ANAME_SZ + INST_SZ + 3)) {
119 /* des_string_to_key() wants this. If C didn't suck, we could have an
120 anonymous function do this. Even a local one. But it does, so here
121 we are. Calling it ive_got_your_local_function_right_here_buddy()
122 would have been rude.
125 key_to_key(char *user, char *instance, char *realm, char *passwd, C_Block key)
127 memcpy(key, passwd, sizeof(des_cblock));
131 /* Called to see if the user's typed password is valid. We do this by asking
132 the kerberos server for a ticket and checking to see if it gave us one.
133 We need to move the ticketfile first, or otherwise we end up updating the
134 user's tkfile with new tickets. This would break services like zephyr that
135 like to stay authenticated, and it would screw with AFS authentication at
136 some sites. So, we do a quick, painful hack with a tmpfile.
139 kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
145 /* temporarily switch to a new ticketfile.
146 I'm not using tmpnam() because it isn't entirely portable.
147 this could probably be fixed with autoconf. */
148 newtkfile = malloc(80 * sizeof(char));
149 memset(newtkfile, 0, sizeof(newtkfile));
151 sprintf(newtkfile, "/tmp/xscrn-%i", getpid());
153 krb_set_tkt_string(newtkfile);
155 /* encrypt the typed password. if you have an AFS password instead
156 of a kerberos one, you lose *right here*. If you want to use AFS
157 passwords, you can use ka_StringToKey() instead. As always, ymmv. */
158 des_string_to_key(typed_passwd, mitkey);
160 if (krb_get_in_tkt(name, inst, realm, "krbtgt", realm, DEFAULT_TKT_LIFE,
161 key_to_key, NULL, mitkey) != 0) {
167 /* quickly block out the tempfile and password to prevent snooping,
168 then restore the old ticketfile and cleean up a bit. */
171 krb_set_tkt_string(tk_file);
173 memset(mitkey, 0, sizeof(mitkey));
176 /* Did we verify successfully? */
180 #endif /* NO_LOCKING -- whole file */