1 /* kpasswd.c --- verify kerberos passwords.
2 * written by Nat Lanza (magus@cs.cmu.edu) for
3 * xscreensaver, Copyright (c) 1993-1997, 1998, 2000, 2003
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>
30 /* I'm not sure if this is exactly the right test...
31 Might __APPLE__ be defined if this is apple hardware, but not
34 Thanks to Alexei Kosut <akosut@stanford.edu> for the MacOS X code.
41 #if defined(HAVE_DARWIN)
42 # include <Kerberos/Kerberos.h>
43 #elif defined(HAVE_KERBEROS5)
44 # include <kerberosIV/krb.h>
45 # include <kerberosIV/des.h>
46 #else /* !HAVE_KERBEROS5 (meaning Kerberos 4) */
49 #endif /* !HAVE_KERBEROS5 */
51 #if !defined(VMS) && !defined(HAVE_ADJUNCT_PASSWD)
57 # include <sys/param.h>
58 # if _BSDI_VERSION >= 199608
71 /* The user information we need to store */
73 static KLPrincipal princ;
74 #else /* !HAVE_DARWIN */
75 static char realm[REALM_SZ];
76 static char name[ANAME_SZ];
77 static char inst[INST_SZ];
79 #endif /* !HAVE_DARWIN */
82 /* Called at startup to grab user, instance, and realm information
83 from the user's ticketfile (remember, name.inst@realm). Since we're
84 using tf_get_pname(), this should work even if your kerberos username
85 isn't the same as your local username. We grab the ticket at startup
86 time so that even if your ticketfile dies while the screen's locked
87 we'll still have the information to unlock it.
89 Problems: the password dialog currently displays local username, so if
90 you have some non-standard name/instance when you run xscreensaver,
91 you'll need to remember what it was when unlocking, or else you lose.
93 Also, we use des_string_to_key(), so if you have an AFS password
94 (encrypted with ka_StringToKey()), you'll lose. Get a kerberos password;
97 Like the original lock_init, we return false if something went wrong.
98 We don't use the arguments we're given, though.
101 kerberos_lock_init (int argc, char **argv, Bool verbose_p)
106 return ((klNoErr == (KLCacheHasValidTickets (NULL, kerberosVersion_Any,
107 &found, &princ, NULL)))
110 # else /* !HAVE_DARWIN */
112 /* Perhaps we should be doing it the Mac way (above) all the time?
113 The following code assumes Unix-style file-based Kerberos credentials
114 cache, which Mac OS X doesn't use. But is there any real reason to
115 do it this way at all, even on other Unixen?
119 memset(name, 0, sizeof(name));
120 memset(inst, 0, sizeof(inst));
122 /* find out where the user's keeping his tickets.
123 squirrel it away for later use. */
124 tk_file = tkt_string();
126 /* open ticket file or die trying. */
127 if ((k_errno = tf_init(tk_file, R_TKT_FIL))) {
131 /* same with principal and instance names */
132 if ((k_errno = tf_get_pname(name)) ||
133 (k_errno = tf_get_pinst(inst))) {
137 /* close the ticketfile to release the lock on it. */
140 /* figure out what realm we're authenticated to. this ought
141 to be the local realm, but it pays to be sure. */
142 if ((k_errno = krb_get_tf_realm(tk_file, realm))) {
146 /* last-minute sanity check on what we got. */
147 if ((strlen(name)+strlen(inst)+strlen(realm)+3) >
148 (REALM_SZ + ANAME_SZ + INST_SZ + 3)) {
155 # endif /* !HAVE_DARWIN */
159 /* des_string_to_key() wants this. If C didn't suck, we could have an
160 anonymous function do this. Even a local one. But it does, so here
161 we are. Calling it ive_got_your_local_function_right_here_buddy()
162 would have been rude.
166 key_to_key(char *user, char *instance, char *realm, char *passwd, C_Block key)
168 memcpy(key, passwd, sizeof(des_cblock));
171 #endif /* !HAVE_DARWIN */
173 /* Called to see if the user's typed password is valid. We do this by asking
174 the kerberos server for a ticket and checking to see if it gave us one.
175 We need to move the ticketfile first, or otherwise we end up updating the
176 user's tkfile with new tickets. This would break services like zephyr that
177 like to stay authenticated, and it would screw with AFS authentication at
178 some sites. So, we do a quick, painful hack with a tmpfile.
181 kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
185 KLAcquireNewInitialTicketsWithPassword (princ, NULL,
186 typed_passwd, NULL));
187 # else /* !HAVE_DARWIN */
189 /* See comments in kerberos_lock_init -- should we do it the Mac Way
196 /* temporarily switch to a new ticketfile.
197 I'm not using tmpnam() because it isn't entirely portable.
198 this could probably be fixed with autoconf. */
199 newtkfile = malloc(80 * sizeof(char));
200 memset(newtkfile, 0, sizeof(newtkfile));
202 sprintf(newtkfile, "/tmp/xscrn-%i", getpid());
204 krb_set_tkt_string(newtkfile);
206 /* encrypt the typed password. if you have an AFS password instead
207 of a kerberos one, you lose *right here*. If you want to use AFS
208 passwords, you can use ka_StringToKey() instead. As always, ymmv. */
209 des_string_to_key(typed_passwd, mitkey);
211 if (krb_get_in_tkt(name, inst, realm, "krbtgt", realm, DEFAULT_TKT_LIFE,
212 key_to_key, NULL, mitkey) != 0) {
218 /* quickly block out the tempfile and password to prevent snooping,
219 then restore the old ticketfile and cleean up a bit. */
222 krb_set_tkt_string(tk_file);
224 memset(mitkey, 0, sizeof(mitkey));
227 /* Did we verify successfully? */
230 # endif /* !HAVE_DARWIN */
233 #endif /* NO_LOCKING -- whole file */