From: <cli...@li...> - 2008-11-19 23:42:44
|
Send clisp-cvs mailing list submissions to cli...@li... To subscribe or unsubscribe via the World Wide Web, visit https://lists.sourceforge.net/lists/listinfo/clisp-cvs or, via email, send a message with subject or body 'help' to cli...@li... You can reach the person managing the list at cli...@li... When replying, please edit your Subject line so it is more specific than "Re: Contents of clisp-cvs digest..." CLISP CVS commits for today Today's Topics: 1. clisp/doc impext.xml,1.550,1.551 (Sam Steingold) 2. clisp/src ChangeLog, 1.6631, 1.6632 configure.in, 1.162, 1.163 spvw.d, 1.449, 1.450 unix.d, 1.104, 1.105 unixaux.d, 1.62, 1.63 (Sam Steingold) 3. clisp configure,1.138,1.139 (Sam Steingold) 4. clisp/src ChangeLog,1.6632,1.6633 makemake.in,1.790,1.791 (Sam Steingold) 5. clisp/src ChangeLog,1.6633,1.6634 spvw.d,1.450,1.451 (Sam Steingold) 6. clisp/src config.h.in,1.24,1.25 configure,1.227,1.228 (Sam Steingold) 7. clisp/src zthread.d,1.16,1.17 (Sam Steingold) ---------------------------------------------------------------------- Message: 1 Date: Wed, 19 Nov 2008 22:11:00 +0000 From: Sam Steingold <sd...@us...> Subject: clisp/doc impext.xml,1.550,1.551 To: cli...@li... Message-ID: <E1L...@dd...> Update of /cvsroot/clisp/clisp/doc In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv23789/doc Modified Files: impext.xml Log Message: drop privileges when running suid root and receive a --clisp- superarg * unix.d (drop_privileges): declare * unixaux.d (drop_privileges): implement, based on http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf * spvw.d (parse_options): call it when receive a --clisp- superarg (main): run *init-hooks* _before_ initializing O(argv) so that applications cannot detect and thus disable "--clisp-" superarg * configure.in: check for getresuid setresuid getresgid setresgid setreuid setregid Index: impext.xml =================================================================== RCS file: /cvsroot/clisp/clisp/doc/impext.xml,v retrieving revision 1.550 retrieving revision 1.551 diff -u -d -r1.550 -r1.551 --- impext.xml 10 Nov 2008 04:31:08 -0000 1.550 +++ impext.xml 19 Nov 2008 22:10:58 -0000 1.551 @@ -164,18 +164,11 @@ 2432902008176640000</screen> These instructions are also printed by <option>--clisp--help</option>.</para> - <para>Of course, this feature opens a security hole if the - application is running <function role="unix">setuid</function> root. - In that case you need to also do this:<programlisting language="lisp"> -(&push; (&lambda-m; () - (&when; (&find-if; (&lambda-m; (o) - (&and-m; (≤ #1=(length #2="--clisp-") (&length; o)) - (&string-eq; o #2# :end1 #1#))) - (&argv;)) - (&setf; (<link linkend="getuid">POSIX:UID</link>) - (POSIX:USER-INFO-UID (<link linkend="user-info">POSIX:USER-INFO</link> :DEFAULT))))) - &init-hooks;)</programlisting></para></listitem></varlistentry> -</variablelist> + <simpara>Of course, this feature opens a <emphasis>security hole</emphasis> + if the application is running <function role="unix">setuid</function> root, + therefore &clisp; resets the effective group and user IDs to the real + ones if it sees a <literal>"--clisp-*"</literal> option. +</simpara></listitem></varlistentry></variablelist> You can use this memory image with the &opt-M; option. On &unix; systems, you may compress it with &gnu; &gzip; to save disk space.</para> ------------------------------ Message: 2 Date: Wed, 19 Nov 2008 22:11:00 +0000 From: Sam Steingold <sd...@us...> Subject: clisp/src ChangeLog, 1.6631, 1.6632 configure.in, 1.162, 1.163 spvw.d, 1.449, 1.450 unix.d, 1.104, 1.105 unixaux.d, 1.62, 1.63 To: cli...@li... Message-ID: <E1L...@dd...> Update of /cvsroot/clisp/clisp/src In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv23789/src Modified Files: ChangeLog configure.in spvw.d unix.d unixaux.d Log Message: drop privileges when running suid root and receive a --clisp- superarg * unix.d (drop_privileges): declare * unixaux.d (drop_privileges): implement, based on http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf * spvw.d (parse_options): call it when receive a --clisp- superarg (main): run *init-hooks* _before_ initializing O(argv) so that applications cannot detect and thus disable "--clisp-" superarg * configure.in: check for getresuid setresuid getresgid setresgid setreuid setregid Index: spvw.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/spvw.d,v retrieving revision 1.449 retrieving revision 1.450 diff -u -d -r1.449 -r1.450 --- spvw.d 19 Nov 2008 19:04:43 -0000 1.449 +++ spvw.d 19 Nov 2008 22:10:58 -0000 1.450 @@ -2431,6 +2431,12 @@ return delegating_cookie[delegating_cookie_length-1] == 'Y'; } +#if defined(UNIX) + #define DROP_PRIVILEGES drop_privileges() +#else + #define DROP_PRIVILEGES /*noop*/ +#endif + /* Parse the command-line options. Returns -1 on normal termination, or an exit code >= 0 for immediate exit. */ local inline int parse_options (int argc, const char* const* argv, @@ -2520,12 +2526,14 @@ var const char* const* argptr = &argv[1]; var const char* const* argptr_limit = &argv[argc]; var enum { for_exec, for_init, for_compile, for_expr, for_load_path } - argv_for = for_exec; + argv_for = for_exec; + var bool clisp_superarg_used = false; /* loop and process options, replace processed options with NULL: */ while (argptr < argptr_limit) { var const char* arg = *argptr++; /* next argument */ - if (0 == strncmp(arg,"--clisp",7)) arg += 7; - else if (delegating) goto non_option; + if (0 == strncmp(arg,"--clisp",7)) { + arg += 7; clisp_superarg_used = true; + } else if (delegating) goto non_option; if ((arg[0] == '-') && !(arg[1] == '\0')) { switch (arg[1]) { case 'h': /* help */ @@ -2868,6 +2876,7 @@ argv_for = for_exec; } } + if (clisp_superarg_used) DROP_PRIVILEGES; p2->argv_batchmode_p = /* '-c' or '-x' or file => batch-mode: */ ((p2->argv_compile || p2->argv_expr_count || p2->argv_execute_file != NULL) && p2->argv_on_error != ON_ERROR_DEBUG @@ -3877,6 +3886,10 @@ (*module->initfunction2)(module); }); } + /* do this before O(argv) is ready so that applications cannot + detect and thus disable "--clisp-" superarg + http://clisp.podval.org/impnotes/image.html#image-exec */ + run_hooks(Symbol_value(S(init_hooks))); { /* Init O(argv). */ O(argv) = allocate_vector(argc); var argc_t count; @@ -3885,10 +3898,6 @@ TheSvector(O(argv))->data[count] = arg; } } - /* do this after O(argv) is reado so that applications can detect "--clisp-" - options and remove setuid bits from the executable image. - http://clisp.podval.org/impnotes/image.html#image-exec */ - run_hooks(Symbol_value(S(init_hooks))); /* Perform the desired actions (compilations, read-eval-print loop etc.): */ #if defined(MULTITHREAD) /* may be set it as command line parameter - it should be big enough */ Index: ChangeLog =================================================================== RCS file: /cvsroot/clisp/clisp/src/ChangeLog,v retrieving revision 1.6631 retrieving revision 1.6632 diff -u -d -r1.6631 -r1.6632 --- ChangeLog 19 Nov 2008 20:50:04 -0000 1.6631 +++ ChangeLog 19 Nov 2008 22:10:58 -0000 1.6632 @@ -1,5 +1,17 @@ 2008-11-19 Sam Steingold <sd...@gn...> + drop privileges when running suid root and receive a --clisp- superarg + * unix.d (drop_privileges): declare + * unixaux.d (drop_privileges): implement, based on + http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf + * spvw.d (parse_options): call it when receive a --clisp- superarg + (main): run *init-hooks* _before_ initializing O(argv) so that + applications cannot detect and thus disable "--clisp-" superarg + * configure.in: check for + getresuid setresuid getresgid setresgid setreuid setregid + +2008-11-19 Sam Steingold <sd...@gn...> + * zthread.d (MAKE-THREAD): use check_list instead of error_list and check_string instead of check_string_replacement (MAKE-MUTEX, MAKE-EXEMPTION): use check_string instead of Index: unixaux.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/unixaux.d,v retrieving revision 1.62 retrieving revision 1.63 diff -u -d -r1.62 -r1.63 --- unixaux.d 17 Nov 2008 23:15:18 -0000 1.62 +++ unixaux.d 19 Nov 2008 22:10:58 -0000 1.63 @@ -1,7 +1,7 @@ /* * Auxiliary functions for CLISP on UNIX * Bruno Haible 1990-2008 - * Sam Steingold 1998-2005 + * Sam Steingold 1998-2008 */ #include "lispbibl.c" @@ -837,3 +837,72 @@ /* if the file IDs are identical, return 1, otherwise return 0 */ global int file_id_eq (struct file_id *fi1, struct file_id *fi2) { return (fi1->device == fi2->device) && (fi1->inode == fi2->inode); } + +/* ======================================================================== */ +/* http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf */ +#define SYSCALL(f,a) if (f a < 0) { \ + perror(STRING(f)); \ + abort(); \ + } +global void drop_privileges (void) { + { /* first group, then user */ + var gid_t gid = getgid(), r, e, s; + if (gid != getegid()) { + #if defined(HAVE_GETRESGID) && defined(HAVE_SETRESGID) + SYSCALL(setresgid,(gid,gid,gid)); + SYSCALL(getresgid,(&r,&e,&s)); + if (gid != r || gid != e || gid != s) { + fprintf(stderr,"Failed to drop group privileges(%ld): %ld %ld %ld\n", + (long)gid,(long)r,(long)e,(long)s); + abort(); + } + #elif defined(HAVE_SETREGID) + SYSCALL(setregid,(gid,gid)); + r = getgid(); e = getegid(); + if (gid != r || gid != e) { + fprintf(stderr,"Failed to drop group privileges(%ld): %ld %ld\n", + (long)gid,(long)r,(long)e); + abort(); + } + #else + SYSCALL(setegid,(gid)); SYSCALL(setgid,(gid)); + r = getgid(); e = getegid(); + if (gid != r || gid != e) { + fprintf(stderr,"Failed to drop group privileges(%ld): %ld %ld\n", + (long)gid,(long)r,(long)e); + abort(); + } + #endif + } + } + { + var uid_t uid = getuid(), r, e, s; + if (uid != geteuid()) { + #if defined(HAVE_GETRESUID) && defined(HAVE_SETRESUID) + SYSCALL(setresuid,(uid,uid,uid)); + SYSCALL(getresuid,(&r,&e,&s)); + if (uid != r || uid != e || uid != s) { + fprintf(stderr,"Failed to drop user privileges(%ld): %ld %ld %ld\n", + (long)uid,(long)r,(long)e,(long)s); + abort(); + } + #elif defined(HAVE_SETREUID) + SYSCALL(setreuid,(uid,uid)); + r = getuid(); e = geteuid(); + if (uid != r || uid != e) { + fprintf(stderr,"Failed to drop user privileges(%ld): %ld %ld\n", + (long)uid,(long)r,(long)e); + abort(); + } + #else + SYSCALL(seteuid,(uid)); SYSCALL(setuid,(uid)); + r = getuid(); e = geteuid(); + if (uid != r || uid != e) { + fprintf(stderr,"Failed to drop user privileges(%ld): %ld %ld\n", + (long)uid,(long)r,(long)e); + abort(); + } + #endif + } + } +} Index: unix.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/unix.d,v retrieving revision 1.104 retrieving revision 1.105 diff -u -d -r1.104 -r1.105 --- unix.d 17 Nov 2008 23:15:18 -0000 1.104 +++ unix.d 19 Nov 2008 22:10:58 -0000 1.105 @@ -729,3 +729,6 @@ /* close all file descriptors before exec() */ global void close_all_fd (void); + +/* remove the effects of the setuid bit on the executable */ +global void drop_privileges (void); Index: configure.in =================================================================== RCS file: /cvsroot/clisp/clisp/src/configure.in,v retrieving revision 1.162 retrieving revision 1.163 diff -u -d -r1.162 -r1.163 --- configure.in 17 Nov 2008 23:15:18 -0000 1.162 +++ configure.in 19 Nov 2008 22:10:58 -0000 1.163 @@ -105,6 +105,7 @@ CL_SIGINTERRUPT dnl DEFS HAVE_SIGINTERRUPT AC_CHECK_FUNCS(strerror sysconf getdtablesize memset setsid setpgid fchmod dnl fsync flock gethostent shutdown usleep ualarm setitimer nice ftime realpath dnl +getresuid setresuid getresgid setresgid setreuid setregid dnl gethostname readlink getcwd uname) CL_PUTENV dnl DEFS HAVE_PUTENV, HAVE_SETENV gt_LC_MESSAGES dnl DEFS HAVE_LC_MESSAGES ------------------------------ Message: 3 Date: Wed, 19 Nov 2008 22:24:08 +0000 From: Sam Steingold <sd...@us...> Subject: clisp configure,1.138,1.139 To: cli...@li... Message-ID: <E1L...@dd...> Update of /cvsroot/clisp/clisp In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv24898 Modified Files: configure Log Message: (--with-threads): remove POSIXOLD_THREADS and C_THREADS Index: configure =================================================================== RCS file: /cvsroot/clisp/clisp/configure,v retrieving revision 1.138 retrieving revision 1.139 diff -u -d -r1.138 -r1.139 --- configure 29 Oct 2008 18:27:19 -0000 1.138 +++ configure 19 Nov 2008 22:24:06 -0000 1.139 @@ -71,9 +71,8 @@ --without-unicode no UNICODE support: character=8bit --without-readline do not link with GNU readline --with-threads=FLAVOR support multiple threads in one CLISP image - via OS threads [highly experimental - use at your own risk] - FLAVORs = POSIX_THREADS POSIXOLD_THREADS SOLARIS_THREADS - C_THREADS WIN32_THREADS + via OS threads [highly experimental - use at your own risk] + FLAVOR: POSIX_THREADS SOLARIS_THREADS WIN32_THREADS --with-jitc=FLAVOR use a given Just-In-Time Compiler. The only flavor at this time is lightning (GNU lightning must be installed in the standard place). ------------------------------ Message: 4 Date: Wed, 19 Nov 2008 22:24:08 +0000 From: Sam Steingold <sd...@us...> Subject: clisp/src ChangeLog,1.6632,1.6633 makemake.in,1.790,1.791 To: cli...@li... Message-ID: <E1L...@dd...> Update of /cvsroot/clisp/clisp/src In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv24898/src Modified Files: ChangeLog makemake.in Log Message: (--with-threads): remove POSIXOLD_THREADS and C_THREADS Index: makemake.in =================================================================== RCS file: /cvsroot/clisp/clisp/src/makemake.in,v retrieving revision 1.790 retrieving revision 1.791 diff -u -d -r1.790 -r1.791 --- makemake.in 11 Nov 2008 17:30:51 -0000 1.790 +++ makemake.in 19 Nov 2008 22:24:06 -0000 1.791 @@ -55,8 +55,7 @@ --with-dynamic-ffi a foreign language interface --with-dynamic-modules dynamic loading of foreign language modules --with-threads=FLAVOR MT [_experimental_!] - FLAVOR: POSIX_THREADS POSIXOLD_THREADS - SOLARIS_THREADS C_THREADS WIN32_THREADS + FLAVOR: POSIX_THREADS SOLARIS_THREADS WIN32_THREADS --with-jitc=FLAVOR use a given Just-In-Time Compiler. The only flavor at this time is lightning (GNU lightning must be installed in the standard place). Index: ChangeLog =================================================================== RCS file: /cvsroot/clisp/clisp/src/ChangeLog,v retrieving revision 1.6632 retrieving revision 1.6633 diff -u -d -r1.6632 -r1.6633 --- ChangeLog 19 Nov 2008 22:10:58 -0000 1.6632 +++ ChangeLog 19 Nov 2008 22:24:06 -0000 1.6633 @@ -1,5 +1,10 @@ 2008-11-19 Sam Steingold <sd...@gn...> + * configure, makemake.in (--with-threads): + remove POSIXOLD_THREADS and C_THREADS + +2008-11-19 Sam Steingold <sd...@gn...> + drop privileges when running suid root and receive a --clisp- superarg * unix.d (drop_privileges): declare * unixaux.d (drop_privileges): implement, based on ------------------------------ Message: 5 Date: Wed, 19 Nov 2008 22:26:20 +0000 From: Sam Steingold <sd...@us...> Subject: clisp/src ChangeLog,1.6633,1.6634 spvw.d,1.450,1.451 To: cli...@li... Message-ID: <E1L...@dd...> Update of /cvsroot/clisp/clisp/src In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv25014/src Modified Files: ChangeLog spvw.d Log Message: remove POSIXOLD_THREADS Index: spvw.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/spvw.d,v retrieving revision 1.450 retrieving revision 1.451 diff -u -d -r1.450 -r1.451 --- spvw.d 19 Nov 2008 22:10:58 -0000 1.450 +++ spvw.d 19 Nov 2008 22:26:18 -0000 1.451 @@ -330,7 +330,7 @@ global xthread_t thr_signal_handler; /* the id of the signal handling thread */ /* POSIX threads with no recursive mutex support */ -#if (defined(POSIX_THREADS) || defined(POSIXOLD_THREADS)) && !defined(PTHREAD_MUTEX_RECURSIVE_NP) +#if defined(POSIX_THREADS) && !defined(PTHREAD_MUTEX_RECURSIVE_NP) /* cache the global mutex attribute for recursive mutex creation */ global pthread_mutexattr_t recursive_mutexattr; #endif @@ -472,7 +472,7 @@ as a chroot program, so reading /proc/self/maps could fail. */ - #if defined(POSIX_THREADS) || defined(POSIXOLD_THREADS) + #if defined(POSIX_THREADS) /* there is difference between the main thread stack base/size and the ones created via pthread_create(). For the latter we will use pthread_getattr_np(), however it returns bogus values for the main thread Index: ChangeLog =================================================================== RCS file: /cvsroot/clisp/clisp/src/ChangeLog,v retrieving revision 1.6633 retrieving revision 1.6634 diff -u -d -r1.6633 -r1.6634 --- ChangeLog 19 Nov 2008 22:24:06 -0000 1.6633 +++ ChangeLog 19 Nov 2008 22:26:18 -0000 1.6634 @@ -1,7 +1,6 @@ 2008-11-19 Sam Steingold <sd...@gn...> - * configure, makemake.in (--with-threads): - remove POSIXOLD_THREADS and C_THREADS + * configure, makemake.in, spvw.d: remove POSIXOLD_THREADS and C_THREADS 2008-11-19 Sam Steingold <sd...@gn...> ------------------------------ Message: 6 Date: Wed, 19 Nov 2008 22:34:14 +0000 From: Sam Steingold <sd...@us...> Subject: clisp/src config.h.in,1.24,1.25 configure,1.227,1.228 To: cli...@li... Message-ID: <E1L...@dd...> Update of /cvsroot/clisp/clisp/src In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv25549/src Modified Files: config.h.in configure Log Message: regenerated for drop_privileges Index: config.h.in =================================================================== RCS file: /cvsroot/clisp/clisp/src/config.h.in,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- config.h.in 17 Nov 2008 23:16:43 -0000 1.24 +++ config.h.in 19 Nov 2008 22:34:11 -0000 1.25 @@ -199,6 +199,12 @@ /* have getpagesize() */ #undef HAVE_GETPAGESIZE +/* Define to 1 if you have the `getresgid' function. */ +#undef HAVE_GETRESGID + +/* Define to 1 if you have the `getresuid' function. */ +#undef HAVE_GETRESUID + /* Define to 1 if you have the `getrlimit' function. */ #undef HAVE_GETRLIMIT @@ -379,6 +385,18 @@ /* Define to 1 if you have the `setpgid' function. */ #undef HAVE_SETPGID +/* Define to 1 if you have the `setregid' function. */ +#undef HAVE_SETREGID + +/* Define to 1 if you have the `setresgid' function. */ +#undef HAVE_SETRESGID + +/* Define to 1 if you have the `setresuid' function. */ +#undef HAVE_SETRESUID + +/* Define to 1 if you have the `setreuid' function. */ +#undef HAVE_SETREUID + /* Define to 1 if you have the `setrlimit' function. */ #undef HAVE_SETRLIMIT Index: configure =================================================================== RCS file: /cvsroot/clisp/clisp/src/configure,v retrieving revision 1.227 retrieving revision 1.228 diff -u -d -r1.227 -r1.228 --- configure 17 Nov 2008 23:16:43 -0000 1.227 +++ configure 19 Nov 2008 22:34:11 -0000 1.228 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Id: configure.in,v 1.161 2008/11/17 19:48:58 sds Exp . +# From configure.in Id: configure.in,v 1.163 2008/11/19 22:10:58 sds Exp . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.62 for GNU CLISP 2.47+ (2008-10-24). # @@ -39344,7 +39344,13 @@ -for ac_func in strerror sysconf getdtablesize memset setsid setpgid fchmod fsync flock gethostent shutdown usleep ualarm setitimer nice ftime realpath gethostname readlink getcwd uname + + + + + + +for ac_func in strerror sysconf getdtablesize memset setsid setpgid fchmod fsync flock gethostent shutdown usleep ualarm setitimer nice ftime realpath getresuid setresuid getresgid setresgid setreuid setregid gethostname readlink getcwd uname do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 ------------------------------ Message: 7 Date: Wed, 19 Nov 2008 23:42:39 +0000 From: Sam Steingold <sd...@us...> Subject: clisp/src zthread.d,1.16,1.17 To: cli...@li... Message-ID: <E1L...@dd...> Update of /cvsroot/clisp/clisp/src In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv29236 Modified Files: zthread.d Log Message: fix last patch Index: zthread.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/zthread.d,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- zthread.d 19 Nov 2008 20:50:04 -0000 1.16 +++ zthread.d 19 Nov 2008 23:42:37 -0000 1.17 @@ -159,7 +159,8 @@ if (!boundp(STACK_0)) /* if not bound set to mt:*default-special-bidnings* */ STACK_0 = Symbol_value(S(default_special_bindings)); STACK_0 = check_list(STACK_0); - STACK_1 = check_string(STACK_1); /* check thread name */ + if (boundp(STACK_1)) + STACK_1 = check_string(STACK_1); /* check thread name */ /* do allocations before thread locking */ pushSTACK(allocate_thread(&STACK_1)); /* put it in GC visible place */ ------------------------------ ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ------------------------------ _______________________________________________ clisp-cvs mailing list cli...@li... https://lists.sourceforge.net/lists/listinfo/clisp-cvs End of clisp-cvs Digest, Vol 31, Issue 32 ***************************************** |