Hello community, here is the log from the commit of package trousers for openSUSE:Factory checked in at Thu Jun 30 16:24:38 CEST 2011.
-------- --- trousers/trousers.changes 2010-09-27 01:39:02.000000000 +0200 +++ /mounts/work_src_done/STABLE/trousers/trousers.changes 2011-06-20 12:00:55.000000000 +0200 @@ -1,0 +2,7 @@ +Mon Jun 20 11:57:28 CEST 2011 - [email protected] + +- Updated to TROUSERS_0_3_7 + - bugfixes + - obj_policy_is_secret_set added + +------------------------------------------------------------------- calling whatdependson for head-i586 Old: ---- trousers-0.3.6.diff trousers-0.3.6.tar.bz2 New: ---- trousers-0.3.7.diff trousers-0.3.7.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ trousers.spec ++++++ --- /var/tmp/diff_new_pack.Q9Gp07/_old 2011-06-30 16:24:06.000000000 +0200 +++ /var/tmp/diff_new_pack.Q9Gp07/_new 2011-06-30 16:24:06.000000000 +0200 @@ -1,7 +1,7 @@ # -# spec file for package trousers (Version 0.3.6) +# spec file for package trousers # -# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -23,8 +23,8 @@ License: Other uncritical OpenSource License Group: Productivity/Security AutoReqProv: on -Version: 0.3.6 -Release: 2 +Version: 0.3.7 +Release: 1 Summary: TSS (TCG Software Stack) access daemon for a TPM chip Source0: %name-%version.tar.bz2 Source1: tcsd.init ++++++ trousers-0.3.6.diff -> trousers-0.3.7.diff ++++++ ++++++ trousers-0.3.6.tar.bz2 -> trousers-0.3.7.tar.bz2 ++++++ ++++ 25824 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/configure.in new/trousers-0.3.7/configure.in --- old/trousers-0.3.6/configure.in 2010-07-08 22:35:18.000000000 +0200 +++ new/trousers-0.3.7/configure.in 2011-06-17 16:20:32.000000000 +0200 @@ -2,7 +2,7 @@ # configure.in for the trousers project # -AC_INIT(trousers, 0.3.6, [email protected]) +AC_INIT(trousers, 0.3.7, [email protected]) TSS_SPEC_MAJOR=1 TSS_SPEC_MINOR=2 @@ -351,6 +351,7 @@ AC_C_BIGENDIAN([AC_DEFINE(_BIG_ENDIAN, 1, [big-endian host])]) AC_CHECK_DECL(htole32, [AC_DEFINE(HTOLE_DEFINED, 1, [htole32 function is available])]) +AC_CHECK_HEADER(endian.h, [AC_DEFINE(HAVE_ENDIAN_H, 1, [endian.h header])]) AC_CHECK_HEADER(sys/byteorder.h, [AC_DEFINE(HAVE_BYTEORDER_H, 1, [sys/byteorder.h header])]) AC_CHECK_FUNC(daemon, [ AC_DEFINE(HAVE_DAEMON, 1, [daemon function is available]) ]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/include/obj_policy.h new/trousers-0.3.7/src/include/obj_policy.h --- old/trousers-0.3.6/src/include/obj_policy.h 2010-03-11 21:27:03.000000000 +0100 +++ new/trousers-0.3.7/src/include/obj_policy.h 2010-09-10 21:50:27.000000000 +0200 @@ -152,6 +152,7 @@ TSS_RESULT obj_policy_get_xsap_params(TSS_HPOLICY, TPM_COMMAND_CODE, TPM_ENTITY_TYPE *, UINT32 *, BYTE **, BYTE *, TSS_CALLBACK *, TSS_CALLBACK *, TSS_CALLBACK *, UINT32 *, TSS_BOOL); +TSS_RESULT obj_policy_is_secret_set(TSS_HPOLICY, TSS_BOOL *); #ifdef TSS_BUILD_DELEGATION TSS_RESULT obj_policy_set_delegation_type(TSS_HPOLICY, UINT32); TSS_RESULT obj_policy_get_delegation_type(TSS_HPOLICY, UINT32 *); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tcs/ps/ps_utils.c new/trousers-0.3.7/src/tcs/ps/ps_utils.c --- old/trousers-0.3.6/src/tcs/ps/ps_utils.c 2010-06-30 17:15:00.000000000 +0200 +++ new/trousers-0.3.7/src/tcs/ps/ps_utils.c 2010-09-10 21:50:27.000000000 +0200 @@ -419,7 +419,7 @@ } tmp->pub_data_size = LE_16(tmp->pub_data_size); - //DBG_ASSERT(tmp->pub_data_size <= 2048 && tmp->pub_data_size > 0); + DBG_ASSERT(tmp->pub_data_size <= 2048 && tmp->pub_data_size > 0); /* blob size */ if ((rc = read_data(fd, &tmp->blob_size, sizeof(UINT16)))) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tcs/rpc/tcstp/rpc_daa.c new/trousers-0.3.7/src/tcs/rpc/tcstp/rpc_daa.c --- old/trousers-0.3.6/src/tcs/rpc/tcstp/rpc_daa.c 2010-06-09 22:18:45.000000000 +0200 +++ new/trousers-0.3.7/src/tcs/rpc/tcstp/rpc_daa.c 2010-09-10 21:50:27.000000000 +0200 @@ -41,10 +41,9 @@ if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm)) return TCSERR(TSS_E_INTERNAL_ERROR); - LogDebugFn("thread %ld hDAA %x", THREAD_ID, hDAA); - if (getData(TCSD_PACKET_TYPE_UINT32, 1, &hDAA, 0, &data->comm)) return TCSERR(TSS_E_INTERNAL_ERROR); + LogDebugFn("thread %ld hDAA %x", THREAD_ID, hDAA); if (getData(TCSD_PACKET_TYPE_BYTE, 2, &stage, 0, &data->comm)) return TCSERR(TSS_E_INTERNAL_ERROR); @@ -145,9 +144,9 @@ if (getData(TCSD_PACKET_TYPE_UINT32, 0, &hContext, 0, &data->comm)) return TCSERR(TSS_E_INTERNAL_ERROR); - LogDebugFn("thread %ld hDAA %x", THREAD_ID, hDAA); if (getData(TCSD_PACKET_TYPE_UINT32, 1, &hDAA, 0, &data->comm)) return TCSERR(TSS_E_INTERNAL_ERROR); + LogDebugFn("thread %ld hDAA %x", THREAD_ID, hDAA); if (getData(TCSD_PACKET_TYPE_BYTE, 2, &stage, 0, &data->comm)) return TCSERR(TSS_E_INTERNAL_ERROR); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tcs/tcs_pbg.c new/trousers-0.3.7/src/tcs/tcs_pbg.c --- old/trousers-0.3.6/src/tcs/tcs_pbg.c 2010-06-14 01:39:18.000000000 +0200 +++ new/trousers-0.3.7/src/tcs/tcs_pbg.c 2010-09-10 21:50:27.000000000 +0200 @@ -916,6 +916,7 @@ tpm_rqu_build(TPM_COMMAND_CODE ordinal, UINT64 *outOffset, BYTE *out_blob, ...) { TSS_RESULT result = TSS_SUCCESS; + UINT64 blob_size; va_list ap; DBG_ASSERT(ordinal); @@ -1448,6 +1449,13 @@ TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); va_end(ap); + blob_size = in_len1 + in_len2 + TPM_DIGEST_SIZE + sizeof(TPM_AUTH); + if (blob_size > TSS_TPM_TXBLOB_SIZE) { + result = TCSERR(TSS_E_BAD_PARAMETER); + LogError("Oversized input when building ordinal 0x%x", ordinal); + break; + } + if (!keySlot1 || !in_blob2 || !auth1) { result = TCSERR(TSS_E_INTERNAL_ERROR); LogError("Internal error for ordinal 0x%x", ordinal); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tcsd/svrside.c new/trousers-0.3.7/src/tcsd/svrside.c --- old/trousers-0.3.6/src/tcsd/svrside.c 2010-06-09 22:19:00.000000000 +0200 +++ new/trousers-0.3.7/src/tcsd/svrside.c 2010-09-10 21:50:27.000000000 +0200 @@ -43,6 +43,7 @@ struct tpm_properties tpm_metrics; static volatile int hup = 0, term = 0; extern char *optarg; +int sd; static void tcsd_shutdown(void) @@ -61,6 +62,7 @@ tcsd_signal_term(int signal) { term = 1; + close(sd); } void @@ -213,7 +215,7 @@ { struct sockaddr_in serv_addr, client_addr; TSS_RESULT result; - int sd, newsd, c, option_index = 0; + int newsd, c, option_index = 0; unsigned client_len; char *hostname = NULL; struct passwd *pwd; @@ -339,5 +341,6 @@ } while (term ==0); /* To close correctly, we must receive a SIGTERM */ + tcsd_shutdown(); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tcsd/tcsd_threads.c new/trousers-0.3.7/src/tcsd/tcsd_threads.c --- old/trousers-0.3.6/src/tcsd/tcsd_threads.c 2010-06-09 22:23:09.000000000 +0200 +++ new/trousers-0.3.7/src/tcsd/tcsd_threads.c 2010-09-10 21:50:27.000000000 +0200 @@ -450,9 +450,8 @@ data->thread_id = THREAD_NULL; pthread_mutex_unlock(&(tm->lock)); pthread_exit(NULL); -#else - return NULL; #endif + return NULL; } #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tspi/obj_policy.c new/trousers-0.3.7/src/tspi/obj_policy.c --- old/trousers-0.3.6/src/tspi/obj_policy.c 2010-03-11 21:27:03.000000000 +0100 +++ new/trousers-0.3.7/src/tspi/obj_policy.c 2010-09-10 21:50:27.000000000 +0200 @@ -302,6 +302,25 @@ } TSS_RESULT +obj_policy_is_secret_set(TSS_HPOLICY hPolicy, TSS_BOOL *secretSet) +{ + struct tsp_object *obj; + struct tr_policy_obj *policy; + TSS_RESULT result = TSS_SUCCESS; + + if ((obj = obj_list_get_obj(&policy_list, hPolicy)) == NULL) + return TSPERR(TSS_E_INVALID_HANDLE); + + policy = (struct tr_policy_obj *)obj->data; + + *secretSet = policy->SecretSet; + obj_list_put(&policy_list); + + return result; +} + + +TSS_RESULT obj_policy_set_secret(TSS_HPOLICY hPolicy, TSS_FLAG mode, UINT32 size, BYTE *data) { TCPA_DIGEST digest; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tspi/ps/tspps.c new/trousers-0.3.7/src/tspi/ps/tspps.c --- old/trousers-0.3.6/src/tspi/ps/tspps.c 2010-05-02 04:39:11.000000000 +0200 +++ new/trousers-0.3.7/src/tspi/ps/tspps.c 2010-09-10 21:50:27.000000000 +0200 @@ -48,17 +48,7 @@ #if (defined (__FreeBSD__) || defined (__OpenBSD__)) static MUTEX_DECLARE_INIT(user_ps_path); #endif -#if defined (SOLARIS) -static struct flock fl = { - 0, - 0, - 0, - 0, - 0, - 0, - {0, 0, 0, 0} -}; -#endif +static struct flock fl; /* @@ -164,7 +154,7 @@ TSS_USER_PS_FILE); #endif if (rc == sizeof (buf)) { - LogDebugFn("USER PS: Path to file too long! (> %d bytes)", sizeof (buf)); + LogDebugFn("USER PS: Path to file too long! (> %zd bytes)", sizeof (buf)); } else *file = strdup(buf); @@ -185,12 +175,8 @@ /* check the global file handle first. If it exists, lock it and return */ if (user_ps_fd != -1) { -#if defined (SOLARIS) fl.l_type = F_WRLCK; if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) { -#else - if ((rc = flock(user_ps_fd, LOCK_EX))) { -#endif /* SOLARIS */ LogDebug("USER PS: failed to lock file: %s", strerror(errno)); MUTEX_UNLOCK(user_ps_lock); return TSPERR(TSS_E_INTERNAL_ERROR); @@ -213,12 +199,8 @@ MUTEX_UNLOCK(user_ps_lock); return TSPERR(TSS_E_INTERNAL_ERROR); } -#if defined (SOLARIS) fl.l_type = F_WRLCK; if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) { -#else - if ((rc = flock(user_ps_fd, LOCK_EX))) { -#endif /* SOLARIS */ LogDebug("USER PS: failed to get lock of %s: %s", file_name, strerror(errno)); free(file_name); close(user_ps_fd); @@ -240,12 +222,8 @@ fsync(fd); /* release the file lock */ -#if defined (SOLARIS) fl.l_type = F_UNLCK; if ((rc = fcntl(fd, F_SETLKW, &fl))) { -#else - if ((rc = flock(fd, LOCK_UN))) { -#endif /* SOLARIS */ LogDebug("USER PS: failed to unlock file: %s", strerror(errno)); rc = -1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tspi/tsp_auth.c new/trousers-0.3.7/src/tspi/tsp_auth.c --- old/trousers-0.3.6/src/tspi/tsp_auth.c 2010-03-11 21:36:19.000000000 +0100 +++ new/trousers-0.3.7/src/tspi/tsp_auth.c 2010-09-10 21:50:27.000000000 +0200 @@ -774,7 +774,7 @@ struct authsess **xsess) { TSS_RESULT result; - TSS_BOOL authdatausage = FALSE, req_auth = TRUE, get_child_auth = TRUE; + TSS_BOOL authdatausage = FALSE, req_auth = TRUE, get_child_auth = TRUE, secret_set = FALSE; BYTE hmacBlob[2 * sizeof(TPM_DIGEST)]; UINT64 offset; TSS_BOOL new_secret = TR_SECRET_CTX_NOT_NEW; @@ -921,7 +921,10 @@ goto error; } - if (!sess->hUsageChild) { + if ((result = obj_policy_is_secret_set(sess->hUsageChild, &secret_set))) + goto error; + + if (!secret_set) { result = TSPERR(TSS_E_TSP_AUTHREQUIRED); goto error; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tspi/tspi_context.c new/trousers-0.3.7/src/tspi/tspi_context.c --- old/trousers-0.3.6/src/tspi/tspi_context.c 2010-01-28 17:27:51.000000000 +0100 +++ new/trousers-0.3.7/src/tspi/tspi_context.c 2011-02-21 17:24:44.000000000 +0100 @@ -55,6 +55,8 @@ /* Destroy all objects */ obj_close_context(tspContext); + Tspi_Context_FreeMemory(tspContext, NULL); + /* close the ps file */ PS_close(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tspi/tspi_nv.c new/trousers-0.3.7/src/tspi/tspi_nv.c --- old/trousers-0.3.6/src/tspi/tspi_nv.c 2010-05-02 04:39:11.000000000 +0200 +++ new/trousers-0.3.7/src/tspi/tspi_nv.c 2011-02-21 14:46:27.000000000 +0100 @@ -130,9 +130,12 @@ free_tspi(tspContext, pWritePCR); if ((result = authsess_xsap_init(tspContext, hTpm, hNvstore, need_authdata, - TPM_ORD_NV_DefineSpace, TPM_ET_OWNER, &xsap))) + TPM_ORD_NV_DefineSpace, TPM_ET_OWNER, &xsap))) { + if (result == TSPERR(TSS_E_TSP_AUTHREQUIRED)) + result = TSS_ERROR_CODE(TSS_E_BAD_PARAMETER); return result; - + } + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_NV_DefineSpace); result |= Trspi_HashUpdate(&hashCtx, NVPublic_DataSize, NVPublicData); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/src/tspi/tspi_ps.c new/trousers-0.3.7/src/tspi/tspi_ps.c --- old/trousers-0.3.6/src/tspi/tspi_ps.c 2010-05-03 00:40:25.000000000 +0200 +++ new/trousers-0.3.7/src/tspi/tspi_ps.c 2011-05-17 19:10:43.000000000 +0200 @@ -42,6 +42,8 @@ TCS_KEY_HANDLE tcsKeyHandle; TSS_HKEY parentTspHandle; TCS_LOADKEY_INFO info; + UINT32 ulPubKeyLength; + BYTE *rgbPubKey; if (phKey == NULL) return TSPERR(TSS_E_BAD_PARAMETER); @@ -91,6 +93,19 @@ if ((result = obj_rsakey_add(tspContext, TSS_RSAKEY_FLAG_OWNEREVICT, phKey))) return result; + if ((result = obj_rsakey_set_tcs_handle(*phKey, tcsKeyHandle))) + return result; + + //The cached public key portion of the owner evict key is used + //further by TPM_KEY_CONTROLOWNER command for sanity check + if ((result = Tspi_Key_GetPubKey(*phKey, &ulPubKeyLength, &rgbPubKey))) + return result; + + result = obj_rsakey_set_pubkey(*phKey, FALSE, rgbPubKey); + + free(rgbPubKey); + if (result != TSS_SUCCESS) + return result; } else { if ((result = RPC_GetRegisteredKeyBlob(tspContext, uuidData, &keyBlobSize, &keyBlob))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/trousers-0.3.6/tools/ps_inspect.c new/trousers-0.3.7/tools/ps_inspect.c --- old/trousers-0.3.6/tools/ps_inspect.c 2010-06-30 17:51:32.000000000 +0200 +++ new/trousers-0.3.7/tools/ps_inspect.c 2011-02-21 14:46:27.000000000 +0100 @@ -186,7 +186,7 @@ { int rc, members = 0; UINT32 i; - UINT32 *u32 = (UINT32 *) buf; + UINT32 *u32 = (UINT32 *) &buf; PRINT("version: 0\n"); PRINT("number of keys: %u\n", *u32); @@ -273,11 +273,11 @@ int bad_file_size(UINT32 num_keys, off_t file_size) { - //if ((num_keys * 360) < (unsigned long)file_size) - // return 1; + if ((num_keys * 360) > (unsigned long)file_size) + return 1; - //if ((num_keys * 560) > (unsigned long)file_size) - // return 1; + if ((num_keys * 560) < (unsigned long)file_size) + return 1; return 0; } @@ -298,7 +298,6 @@ } if (buf[0] == '\1') { - printf("lala %d\n", (int) file_size); num_keys = (UINT32 *)&buf[1]; if (*num_keys == 0 || bad_file_size(*num_keys, file_size)) goto version0; @@ -307,9 +306,9 @@ } version0: - num_keys = (UINT32 *)&buf[1]; + num_keys = (UINT32 *)&buf[0]; if (*num_keys == 0 || bad_file_size(*num_keys, file_size)) { - printf("This file does not appear to be a valid PS file. %d\n", (int) *(num_keys)); + printf("This file does not appear to be a valid PS file.\n"); return -1; } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
