Subject: Re: Repost: kerberos, pine and Mac OS X

From: Josh Larios <[email-masked]>
Date: Thu, 12 Jun 2003 16:03:54 -0700 (PDT)

On Sat, 31 May 2003, Michael Bartosh wrote:

> No one ever really replied to this... Just a repost- has anyone managed
> to get kerberized pine to run on Mac OS X? In general I'd rather use
> pine than Mail.app...

Attached is a (completely unofficial) patch against Pine 4.56 which does
the following:

1) adds checks in contrib/krb5-setup for .dylib libraries
2) adds contrib/utils/open-delay, a launcher script for use with mailcap
3) makes auth_gss.c work around a bug in OS X Kerberos
4) changes temp file naming for attachments to include a file extension

1 and 3 make building and running kerberized pine work for me; 2 and 4
make viewing attachments easier.

My build procedure is like so:

tar zxvf pine4.56.tar.gz
cd pine4.56
ln -s /usr krb5
patch -p1 < ../pine456-osx.patch
./build osx EXTRACFLAGS=-DOSX_HACK SSLDIR=/System/Library/OpenSSL/ \
SSLLIB=/usr/lib SSLINCLUDE=/usr/include/openssl

I haven't tested the attachment viewer stuff much, but the kerberos part's
been around for a few versions and has worked pretty well for me.

Yours,

--Josh Larios

diff -Naur pine4.56/contrib/krb5-setup pine4.56-jdl/contrib/krb5-setup
--- pine4.56/contrib/krb5-setup	Fri Feb  4 12:06:29 2000
+++ pine4.56-jdl/contrib/krb5-setup	Thu Jun 12 12:02:11 2003
@@ -74,11 +74,15 @@

 # This is where c-client expects the libraries to be.
-if [ \( -f krb5/lib/libgssapi_krb5.a -o -f krb5/lib/libgssapi_krb5.so \) -a \
-     \( -f krb5/lib/libkrb5.a        -o -f krb5/lib/libkrb5.so \)        -a \
+if [ \( -f krb5/lib/libgssapi_krb5.a -o -f krb5/lib/libgssapi_krb5.so -o \
+	-f krb5/lib/libgssapi_krb5.dylib \) -a \
+     \( -f krb5/lib/libkrb5.a        -o -f krb5/lib/libkrb5.so  -o \
+        -f krb5/lib/libkrb5.dylib \) -a \
      \( -f krb5/lib/libcrypto.a      -o -f krb5/lib/libk5crypto.a    -o \
-        -f krb5/lib/libcrypto.so     -o -f krb5/lib/libk5crypto.so \)    -a \
-     \( -f krb5/lib/libcom_err.a     -o -f krb5/lib/libcom_err.so \) ]
+        -f krb5/lib/libcrypto.so     -o -f krb5/lib/libk5crypto.so  -o \
+        -f krb5/lib/libcrypto.dylib  -o -f krb5/lib/libk5crypto.dylib \) -a \
+     \( -f krb5/lib/libcom_err.a     -o -f krb5/lib/libcom_err.so -o \
+        -f krb5/lib/libcom_err.dylib \) ]
 then
     exit 0
 fi
diff -Naur pine4.56/contrib/utils/open-delay pine4.56-jdl/contrib/utils/open-delay
--- pine4.56/contrib/utils/open-delay	Wed Dec 31 16:00:00 1969
+++ pine4.56-jdl/contrib/utils/open-delay	Thu Jun 12 15:36:20 2003
@@ -0,0 +1,7 @@
+#!/bin/sh
+# A script to launch the appropriate application to view an attachment in OS X.
+# Call from within mailcap, and it'll probably only work if -DOSX_HACK was
+# part of the build process, and my OSX patch applied to the source.
+# June 12, 2003, Josh Larios <[email-masked]>
+/usr/bin/open "$1"
+sleep 60
diff -Naur pine4.56/imap/src/c-client/auth_gss.c pine4.56-jdl/imap/src/c-client/auth_gss.c
--- pine4.56/imap/src/c-client/auth_gss.c	Tue Mar  4 21:24:17 2003
+++ pine4.56-jdl/imap/src/c-client/auth_gss.c	Thu Jun 12 12:10:27 2003
@@ -111,10 +111,17 @@
   else {
     data = (*bn) (BLOCK_SENSITIVE,NIL);
 				/* negotiate with KDC */
+#ifdef OSX_HACK
+    dup2(0,6);
+    close(0);
+#endif
     smj = gss_init_sec_context (&smn,GSS_C_NO_CREDENTIAL,&ctx,crname,NIL,
 				GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,0,
 				GSS_C_NO_CHANNEL_BINDINGS,GSS_C_NO_BUFFER,NIL,
 				&resp,NIL,NIL);
+#ifdef OSX_HACK
+    dup2(6,0);
+#endif
     (*bn) (BLOCK_NONSENSITIVE,data);
     switch (smj) {
     case GSS_S_CONTINUE_NEEDED:
@@ -126,11 +133,18 @@
 	gss_release_buffer (&smn,&resp);
 	if (i) {		/* negotiate continuation with KDC */
 	  data = (*bn) (BLOCK_SENSITIVE,NIL);
+#ifdef OSX_HACK
+    dup2(0,6);
+    close(0);
+#endif
 	  smj = gss_init_sec_context (&smn,GSS_C_NO_CREDENTIAL,&ctx,crname,
 				      GSS_C_NO_OID,
 				      GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG,0,
 				      GSS_C_NO_CHANNEL_BINDINGS,&chal,NIL,
 				      &resp,NIL,NIL);
+#ifdef OSX_HACK
+    dup2(6,0);
+#endif
 	  (*bn) (BLOCK_NONSENSITIVE,data);
 	}
       } while (i && (smj == GSS_S_CONTINUE_NEEDED));
diff -Naur pine4.56/pine/mailpart.c pine4.56-jdl/pine/mailpart.c
--- pine4.56/pine/mailpart.c	Wed May 28 18:21:12 2003
+++ pine4.56-jdl/pine/mailpart.c	Thu Jun 12 13:47:16 2003
@@ -2084,6 +2084,7 @@
 /*----------------------------------------------------------------------
   Unpack and display the given attachment associated with given message no.
 
+
   Args: msgno -- message no attachment is part of
 	a -- attachment to display
 
@@ -2174,7 +2175,7 @@
 	}
     }
     /*------ Write the image to a temporary file ------*/
-#if defined(DOS) || defined(OS2)
+#if defined(DOS) || defined(OS2) || defined(OSX_HACK)
     /*
      *  Dos applications are particular about the file name extensions
      *  Try to look up the expected extension from the mime.types file.
diff -Naur pine4.56/pine/osdep/os-osx.ic pine4.56-jdl/pine/osdep/os-osx.ic
--- pine4.56/pine/osdep/os-osx.ic	Wed Sep 20 16:45:59 2000
+++ pine4.56-jdl/pine/osdep/os-osx.ic	Thu Jun 12 13:46:22 2003
@@ -60,6 +60,9 @@
 ; function already.
 include(tempfile)
 
+; --JDL
+include(tempnam.osx)
+
 ; Coredump function.  Version called coredump just calls abort, coredump.fpe
 ; uses a floating point exception to cause the coredump on some systems.
 include(coredump)
diff -Naur pine4.56/pine/osdep/tempnam.osx pine4.56-jdl/pine/osdep/tempnam.osx
--- pine4.56/pine/osdep/tempnam.osx	Wed Dec 31 16:00:00 1969
+++ pine4.56-jdl/pine/osdep/tempnam.osx	Thu Jun 12 13:55:53 2003
@@ -0,0 +1,138 @@
+#line 2 "osdep/tempnam.osx"
+/*
+ * This routine is derived from BSD4.3 code,
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tmpnam.c	4.5 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+
+
+/*
+ * Module global.
+ */
+static char *NumTemplate = "XXXXXX";
+
+
+/*----------------------------------------------------------------------
+      Return a unique file name in a given directory.  This is not quite
+      the same as the usual tempnam() function, though it is very similar.
+      We want it to use the TMP environment variable only if dir is NULL,
+      instead of using TMP regardless if it is set.
+
+  Args: dir      -- The directory to create the name in
+        prefix   -- Prefix of the name
+ 
+ Result: Malloc'd string equal to new name is returned.  It must be free'd
+	 by the caller.  Returns the string on success and NULL on failure.
+  ----*/
+static char *
+temp_mkbase (dir, prefix)
+    char *dir, *prefix;
+{
+    struct stat buf;
+    char *f, *name;
+    char *mktemp();
+
+    if (!(name = malloc((unsigned int)MAXPATH)))
+        return(NULL);
+
+    if (!dir && ((f = getenv("TMP")) || (f = getenv("TEMP"))) &&
+			 !stat(f, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR &&
+			 !can_access(f, WRITE_ACCESS)) {
+        (void)strcpy(name, f);
+        goto done;
+    }
+
+    if (dir) {
+	strcpy(name, dir);
+	if(!*dir || (isalpha(*dir) && *(dir+1) == ':' && !*(dir+2)))
+	  strcat(name, "/");
+
+	if((!stat(name, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR)
+		    && !can_access(name, WRITE_ACCESS)) {
+            (void)strcpy(name, dir);
+            goto done;
+	}
+    }
+
+#ifndef P_tmpdir
+#define	P_tmpdir	"/tmp"
+#endif
+    if (!stat(P_tmpdir, &buf) &&
+                         (buf.st_mode&S_IFMT) == S_IFDIR &&
+			 !can_access(P_tmpdir, WRITE_ACCESS)) {
+        (void)strcpy(name, P_tmpdir);
+        goto done;
+    }
+
+    free(name);
+    return(NULL);
+
+done:
+    if(name[0] && name[strlen(name)-1] != '/')
+      (void)strcat(name, "/");
+
+    if (prefix)
+        (void)strcat(name, prefix);
+    (void)strcat(name, NumTemplate);
+    return(name);
+}
+
+
+
+/*----------------------------------------------------------------------
+
+      Like temp_nam but create a unique name _with_ an extension.
+
+  Args: dir      -- The directory to create the name in
+        prefix   -- Prefix of the name
+	ext	 -- Extension to append.
+ 
+ Result: Malloc'd string equal to new name is returned.  It must be free'd
+	 by the caller.  Returns the string on success and NULL on failure.
+  ----*/
+char *
+temp_nam_ext (dir, prefix, ext)
+    char *dir, *prefix, *ext;
+{
+    char *name;
+    char *numberpos;
+    int	 tries;
+    int	 pid;
+
+    name = temp_mkbase (dir, prefix);
+
+    if (name == NULL)				/* Failed to make base name? */
+	return (NULL);
+
+    if (ext == NULL || *ext == '\0')		/* No extension required? */
+	return (mktemp(name));
+
+    if ((numberpos = strstr (name, NumTemplate)) == NULL) {
+	free (name);
+	return (NULL);
+    }
+
+    /*
+     * Start with the PID.  Build file names, incrementing the pid
+     * until we encounter a unique file name.  Don't keep trying for ever.
+     */
+    pid = abs (getpid ());
+    tries = 1000;
+    do {
+	if(pid > 999999)
+	  pid = random() % 999999;
+
+	sprintf (numberpos, "%06d.%s", abs(pid++), ext);
+	if (--tries == 0) {
+	    free (name);
+	    return (NULL);
+	}
+    } while (can_access (name, ACCESS_EXISTS) == 0);
+    return (name);
+}
+
+