http://www.tienza.es/crux/src/www.jwz.org/xscreensaver/xscreensaver-5.06.tar.gz
[xscreensaver] / driver / passwd-kerberos.c
index 1e28d60af27f09c481aff2ebd01914d513d057bd..202e0eb10982395a2f1c1186545c55e7ec4da38e 100644 (file)
@@ -1,6 +1,6 @@
 /* kpasswd.c --- verify kerberos passwords.
  * written by Nat Lanza (magus@cs.cmu.edu) for
- * xscreensaver, Copyright (c) 1993-1997, 1998 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2004 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
-#include <krb.h>
-#include <des.h>
+#include <sys/stat.h>
+
+/* I'm not sure if this is exactly the right test...
+   Might __APPLE__ be defined if this is apple hardware, but not
+   an Apple OS?
+
+   Thanks to Alexei Kosut <akosut@stanford.edu> for the MacOS X code.
+ */
+#ifdef __APPLE__
+# define HAVE_DARWIN
+#endif
+
+
+#if defined(HAVE_DARWIN)
+# include <Kerberos/Kerberos.h>
+#elif defined(HAVE_KERBEROS5)
+# include <kerberosIV/krb.h>
+# include <kerberosIV/des.h>
+#else /* !HAVE_KERBEROS5 (meaning Kerberos 4) */
+# include <krb.h>
+# include <des.h>
+#endif /* !HAVE_KERBEROS5 */
 
 #if !defined(VMS) && !defined(HAVE_ADJUNCT_PASSWD)
 # include <pwd.h>
 #define False 0
 
 /* The user information we need to store */
-static char realm[REALM_SZ];
-static char  name[ANAME_SZ];
-static char  inst[INST_SZ];
-static char *tk_file;
+#ifdef HAVE_DARWIN
+ static KLPrincipal princ;
+#else /* !HAVE_DARWIN */
+ static char realm[REALM_SZ];
+ static char  name[ANAME_SZ];
+ static char  inst[INST_SZ];
+ static const char *tk_file;
+#endif /* !HAVE_DARWIN */
+
+/* warning suppression: duplicated in passwd.c */
+extern Bool kerberos_lock_init (int argc, char **argv, Bool verbose_p);
+extern Bool kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
 
 
 /* Called at startup to grab user, instance, and realm information
@@ -76,6 +104,20 @@ static char *tk_file;
 Bool
 kerberos_lock_init (int argc, char **argv, Bool verbose_p)
 {
+# ifdef HAVE_DARWIN
+
+    KLBoolean found;
+    return ((klNoErr == (KLCacheHasValidTickets (NULL, kerberosVersion_Any,
+                                                 &found, &princ, NULL)))
+            && found);
+
+# else /* !HAVE_DARWIN */
+
+    /* Perhaps we should be doing it the Mac way (above) all the time?
+       The following code assumes Unix-style file-based Kerberos credentials
+       cache, which Mac OS X doesn't use.  But is there any real reason to
+       do it this way at all, even on other Unixen?
+     */
     int k_errno;
     
     memset(name, 0, sizeof(name));
@@ -113,6 +155,8 @@ kerberos_lock_init (int argc, char **argv, Bool verbose_p)
 
     /* success */
     return True;
+
+# endif /* !HAVE_DARWIN */
 }
 
 
@@ -121,12 +165,14 @@ kerberos_lock_init (int argc, char **argv, Bool verbose_p)
    we are. Calling it ive_got_your_local_function_right_here_buddy()
    would have been rude.
  */
+#ifndef HAVE_DARWIN
 static int 
 key_to_key(char *user, char *instance, char *realm, char *passwd, C_Block key)
 {
   memcpy(key, passwd, sizeof(des_cblock));
   return (0);
 }
+#endif /* !HAVE_DARWIN */
 
 /* Called to see if the user's typed password is valid. We do this by asking
    the kerberos server for a ticket and checking to see if it gave us one.
@@ -138,9 +184,19 @@ key_to_key(char *user, char *instance, char *realm, char *passwd, C_Block key)
 Bool
 kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
 {
+# ifdef HAVE_DARWIN
+    return (klNoErr ==
+            KLAcquireNewInitialTicketsWithPassword (princ, NULL,
+                                                    typed_passwd, NULL));
+# else /* !HAVE_DARWIN */
+
+    /* See comments in kerberos_lock_init -- should we do it the Mac Way
+       on all systems?
+     */
     C_Block mitkey;
     Bool success;
     char *newtkfile;
+    int fh = -1;
 
     /* temporarily switch to a new ticketfile.
        I'm not using tmpnam() because it isn't entirely portable.
@@ -148,7 +204,19 @@ kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
     newtkfile = malloc(80 * sizeof(char));
     memset(newtkfile, 0, sizeof(newtkfile));
 
-    sprintf(newtkfile, "/tmp/xscrn-%i", getpid());
+    sprintf(newtkfile, "/tmp/xscrn-%i.XXXXXX", getpid());
+
+    if( (fh = mkstemp(newtkfile)) < 0)
+    {
+        free(newtkfile);
+        return(False);
+    }
+    if( fchmod(fh, 0600) < 0)
+    {
+        free(newtkfile);
+        return(False);
+    }
+
 
     krb_set_tkt_string(newtkfile);
 
@@ -158,7 +226,7 @@ kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
     des_string_to_key(typed_passwd, mitkey);
 
     if (krb_get_in_tkt(name, inst, realm, "krbtgt", realm, DEFAULT_TKT_LIFE,
-                      key_to_key, NULL, mitkey) != 0) {
+                      key_to_key, NULL, (char *) mitkey) != 0) {
        success = False;
     } else {
        success = True;
@@ -171,10 +239,13 @@ kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
     krb_set_tkt_string(tk_file);
     free(newtkfile);
     memset(mitkey, 0, sizeof(mitkey));
+    close(fh); /* #### tom: should the file be removed? */
     
 
     /* Did we verify successfully? */
     return success;
+
+# endif /* !HAVE_DARWIN */
 }
 
 #endif /* NO_LOCKING -- whole file */