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