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>
31 /* I'm not sure if this is exactly the right test...
32 Might __APPLE__ be defined if this is apple hardware, but not
35 Thanks to Alexei Kosut <akosut@stanford.edu> for the MacOS X code.
42 #if defined(HAVE_DARWIN)
43 # include <Kerberos/Kerberos.h>
44 #elif defined(HAVE_KERBEROS5)
45 # include <kerberosIV/krb.h>
46 # include <kerberosIV/des.h>
47 #else /* !HAVE_KERBEROS5 (meaning Kerberos 4) */
50 #endif /* !HAVE_KERBEROS5 */
52 #if !defined(VMS) && !defined(HAVE_ADJUNCT_PASSWD)
58 # include <sys/param.h>
59 # if _BSDI_VERSION >= 199608
72 /* The user information we need to store */
74 static KLPrincipal princ;
75 #else /* !HAVE_DARWIN */
76 static char realm[REALM_SZ];
77 static char name[ANAME_SZ];
78 static char inst[INST_SZ];
80 #endif /* !HAVE_DARWIN */
83 /* Called at startup to grab user, instance, and realm information
84 from the user's ticketfile (remember, name.inst@realm). Since we're
85 using tf_get_pname(), this should work even if your kerberos username
86 isn't the same as your local username. We grab the ticket at startup
87 time so that even if your ticketfile dies while the screen's locked
88 we'll still have the information to unlock it.
90 Problems: the password dialog currently displays local username, so if
91 you have some non-standard name/instance when you run xscreensaver,
92 you'll need to remember what it was when unlocking, or else you lose.
94 Also, we use des_string_to_key(), so if you have an AFS password
95 (encrypted with ka_StringToKey()), you'll lose. Get a kerberos password;
98 Like the original lock_init, we return false if something went wrong.
99 We don't use the arguments we're given, though.
102 kerberos_lock_init (int argc, char **argv, Bool verbose_p)
107 return ((klNoErr == (KLCacheHasValidTickets (NULL, kerberosVersion_Any,
108 &found, &princ, NULL)))
111 # else /* !HAVE_DARWIN */
113 /* Perhaps we should be doing it the Mac way (above) all the time?
114 The following code assumes Unix-style file-based Kerberos credentials
115 cache, which Mac OS X doesn't use. But is there any real reason to
116 do it this way at all, even on other Unixen?
120 memset(name, 0, sizeof(name));
121 memset(inst, 0, sizeof(inst));
123 /* find out where the user's keeping his tickets.
124 squirrel it away for later use. */
125 tk_file = tkt_string();
127 /* open ticket file or die trying. */
128 if ((k_errno = tf_init(tk_file, R_TKT_FIL))) {
132 /* same with principal and instance names */
133 if ((k_errno = tf_get_pname(name)) ||
134 (k_errno = tf_get_pinst(inst))) {
138 /* close the ticketfile to release the lock on it. */
141 /* figure out what realm we're authenticated to. this ought
142 to be the local realm, but it pays to be sure. */
143 if ((k_errno = krb_get_tf_realm(tk_file, realm))) {
147 /* last-minute sanity check on what we got. */
148 if ((strlen(name)+strlen(inst)+strlen(realm)+3) >
149 (REALM_SZ + ANAME_SZ + INST_SZ + 3)) {
156 # endif /* !HAVE_DARWIN */
160 /* des_string_to_key() wants this. If C didn't suck, we could have an
161 anonymous function do this. Even a local one. But it does, so here
162 we are. Calling it ive_got_your_local_function_right_here_buddy()
163 would have been rude.
167 key_to_key(char *user, char *instance, char *realm, char *passwd, C_Block key)
169 memcpy(key, passwd, sizeof(des_cblock));
172 #endif /* !HAVE_DARWIN */
174 /* Called to see if the user's typed password is valid. We do this by asking
175 the kerberos server for a ticket and checking to see if it gave us one.
176 We need to move the ticketfile first, or otherwise we end up updating the
177 user's tkfile with new tickets. This would break services like zephyr that
178 like to stay authenticated, and it would screw with AFS authentication at
179 some sites. So, we do a quick, painful hack with a tmpfile.
182 kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
186 KLAcquireNewInitialTicketsWithPassword (princ, NULL,
187 typed_passwd, NULL));
188 # else /* !HAVE_DARWIN */
190 /* See comments in kerberos_lock_init -- should we do it the Mac Way
198 /* temporarily switch to a new ticketfile.
199 I'm not using tmpnam() because it isn't entirely portable.
200 this could probably be fixed with autoconf. */
201 newtkfile = malloc(80 * sizeof(char));
202 memset(newtkfile, 0, sizeof(newtkfile));
204 sprintf(newtkfile, "/tmp/xscrn-%i.XXXXXX", getpid());
206 if( (fh = mkstemp(newtktfile)) < 0)
211 if( fchmod(fh, 0600) < 0)
218 krb_set_tkt_string(newtkfile);
220 /* encrypt the typed password. if you have an AFS password instead
221 of a kerberos one, you lose *right here*. If you want to use AFS
222 passwords, you can use ka_StringToKey() instead. As always, ymmv. */
223 des_string_to_key(typed_passwd, mitkey);
225 if (krb_get_in_tkt(name, inst, realm, "krbtgt", realm, DEFAULT_TKT_LIFE,
226 key_to_key, NULL, mitkey) != 0) {
232 /* quickly block out the tempfile and password to prevent snooping,
233 then restore the old ticketfile and cleean up a bit. */
236 krb_set_tkt_string(tk_file);
238 memset(mitkey, 0, sizeof(mitkey));
239 close(fh); /* #### tom: should the file be removed? */
242 /* Did we verify successfully? */
245 # endif /* !HAVE_DARWIN */
248 #endif /* NO_LOCKING -- whole file */