Quick question please:
Which does Postfix run first - a milter specified in smtpd_milters or a check_policy_service in smtpd_recipient_restrictions? I.e.: #OpenDKIM smtpd_milters = inet:127.0.0.1:8891 ... smtpd_recipient_restrictions = ... # python-policyd-spf check_policy_service unix:private/policyd-spf permit Thanks. -- Simon Wilson M: 0400 12 11 16 |
On 2021-04-01 01:43, Simon Wilson wrote:
> Quick question please: > > Which does Postfix run first - a milter specified in smtpd_milters or > a check_policy_service in smtpd_recipient_restrictions? milters is run after check policy service, to keep performance at top |
----- Message from Benny Pedersen <[hidden email]> ---------
Date: Thu, 01 Apr 2021 01:50:15 +0200 From: Benny Pedersen <[hidden email]> Subject: Re: Milters and policy To: [hidden email] > On 2021-04-01 01:43, Simon Wilson wrote: >> Quick question please: >> >> Which does Postfix run first - a milter specified in smtpd_milters or >> a check_policy_service in smtpd_recipient_restrictions? > > milters is run after check policy service, to keep performance at top Thank you sir... I just found this too which helped: https://groups.google.com/g/mailing.postfix.users/c/3vGc-RMYV94/m/W3xYtyiovQcJ "...The Milter comes after smtpd/cleanup. Wietse" So in my config above, the SPF policy is run before OpenDKIM milter is called. Simon. -- Simon Wilson M: 0400 12 11 16 |
>>> Quick question please:
>>> >>> Which does Postfix run first - a milter specified in smtpd_milters or >>> a check_policy_service in smtpd_recipient_restrictions? >> >> milters is run after check policy service, to keep performance at top > > Thank you sir... > > I just found this too which helped: > https://groups.google.com/g/mailing.postfix.users/c/3vGc-RMYV94/m/W3xYtyiovQcJ > > "...The Milter comes after smtpd/cleanup. Wietse" > > So in my config above, the SPF policy is run before OpenDKIM milter > is called. > > Simon. ...if multiple milters are called are they run in order specified? smtpd_milters = inet:127.0.0.1:8891,inet:127.0.0.1:8893 I.e. in the example above if OpenDMARC is to see and trust an already-run OpenDKIM Authentication-Results header is the order of specifying the milters important? Simon -- Simon Wilson M: 0400 12 11 16 |
On 2021-04-01 02:29, Simon Wilson wrote:
> ...if multiple milters are called are they run in order specified? > > smtpd_milters = inet:127.0.0.1:8891,inet:127.0.0.1:8893 yes > I.e. in the example above if OpenDMARC is to see and trust an > already-run OpenDKIM Authentication-Results header is the order of > specifying the milters important? yes opendkim need to run before opendmarc, and if you have openarc place that before opendkim, it can be messy if opendmarc checks openarc results, remeber it also need to trust AR headers to be considered good info but i do not use milters self, only do all i need with fuglu |
>> ...if multiple milters are called are they run in order specified?
>> >> smtpd_milters = inet:127.0.0.1:8891,inet:127.0.0.1:8893 > > yes > >> I.e. in the example above if OpenDMARC is to see and trust an >> already-run OpenDKIM Authentication-Results header is the order of >> specifying the milters important? > > yes opendkim need to run before opendmarc, and if you have openarc > place that before opendkim, it can be messy if opendmarc checks > openarc results, remeber it also need to trust AR headers to be > considered good info > > but i do not use milters self, only do all i need with fuglu Thanks again Benny. I have policyd-spf set to insert an AR header, and OpenDMARC set to trust the Authserv-Id added in Authentication-Results headers by policyd-spf and OpenDKIM. All working nicely and good to understand the sequence. Simon. -- Simon Wilson M: 0400 12 11 16 |
> On Mar 31, 2021, at 18:23, Simon Wilson <[hidden email]> wrote: > > >> >>> ...if multiple milters are called are they run in order specified? >>> >>> smtpd_milters = inet:127.0.0.1:8891,inet:127.0.0.1:8893 >> >> yes >> >>> I.e. in the example above if OpenDMARC is to see and trust an >>> already-run OpenDKIM Authentication-Results header is the order of >>> specifying the milters important? >> >> yes opendkim need to run before opendmarc, and if you have openarc place that before opendkim, it can be messy if opendmarc checks openarc results, remeber it also need to trust AR headers to be considered good info >> >> but i do not use milters self, only do all i need with fuglu > > Thanks again Benny. I have policyd-spf set to insert an AR header, and OpenDMARC set to trust the Authserv-Id added in Authentication-Results headers by policyd-spf and OpenDKIM. All working nicely and good to understand the sequence. Please read CVE-2019-20790, and tell me you’ve found a way to tell PyPolicyd not to trust the SMTP HELO to generate a passing AR header. -Dan > > Simon. > > -- > Simon Wilson > M: 0400 12 11 16 |
----- Message from Dan Mahoney <[hidden email]> ---------
Date: Thu, 1 Apr 2021 16:19:05 -0700 From: Dan Mahoney <[hidden email]> Subject: Re: Milters and policy To: [hidden email] Cc: [hidden email] >> On Mar 31, 2021, at 18:23, Simon Wilson <[hidden email]> wrote: >> >> >>> >>>> ...if multiple milters are called are they run in order specified? >>>> >>>> smtpd_milters = inet:127.0.0.1:8891,inet:127.0.0.1:8893 >>> >>> yes >>> >>>> I.e. in the example above if OpenDMARC is to see and trust an >>>> already-run OpenDKIM Authentication-Results header is the order of >>>> specifying the milters important? >>> >>> yes opendkim need to run before opendmarc, and if you have openarc >>> place that before opendkim, it can be messy if opendmarc checks >>> openarc results, remeber it also need to trust AR headers to be >>> considered good info >>> >>> but i do not use milters self, only do all i need with fuglu >> >> Thanks again Benny. I have policyd-spf set to insert an AR header, >> and OpenDMARC set to trust the Authserv-Id added in >> Authentication-Results headers by policyd-spf and OpenDKIM. All >> working nicely and good to understand the sequence. > > Please read CVE-2019-20790, and tell me you’ve found a way to tell > PyPolicyd not to trust the SMTP HELO to generate a passing AR header. > > -Dan > In the interests of open disclosure of your interests, I assume [hidden email] = https://github.com/thegushi = OpenDMARC developer? This is possibly off-topic for the Postfix list... maybe not. Re the risk from the CVE to my setup... I run policyd-spf as a postfix check_policy with reject on fail (on both HELO and MAILFROM), and assuming a mail gets past that (99% do), I then use that Pass along with OpenDKIM and OpenDMARC to contribute to Spamassassin scoring. My DMARC Spamassassin rules do not apply a -ve on a pass, only a +ve on a fail. The impact of a false pass from DMARC (particularly as our Webmail system - Horde - does not show any added trust for a dmarc pass) would be failure to apply a negative Spamassassin score from a the missed DMARC fail. With my mail setup and users the impact of that is probably manageable... but agreed it is not ideal. What concerns me as much as anything is that each of the apps' devs in question (pypolicyd-spf and opendmarc) are each pointing at each other :-/ https://bugs.launchpad.net/pypolicyd-spf/+bug/1838816/comments/4: "my belief that the issue here is a DMARC processor failing to do alignment validation correctly" https://github.com/trusteddomainproject/OpenDMARC/issues/49#issuecomment-802242666 "Honestly, this CVE seems more to belong to py-policyd than OpenDMARC." What would be nice would be if the two of you worked together on coming up with a fix... Anyways... I see two possible workarounds (not fixes). 1. Setting pypolicyd to HELO_Reject = No_Check. RFC7208 indicates that MAILFROM and HELO are both equally valid for an SPF result, *BUT* the vast majority of my SPF checks trigger pass or fail on MAILFROM (I've had 3 spf HELO passes in 10 days on HELO, thousands on MAILFROM). Testing pypolicyd-spf with HELO_reject = No_Check results in spf=none for those. Removing the HELO check means that OpenDMARC can assume any spf result it is given is based on MAILFROM. 2. Tell OpenDMARC to *NOT* trust any existing spf result and do its own. I.e. SPFIgnoreResults true. This obviously doubles SPF processing time, and relegates pypolicyd-spf to purely an inbound policy reject check. If one is not using pypolicyd to reject then this would be pointless, and it could be removed from the stack. Thoughts? > >> >> Simon. >> >> -- >> Simon Wilson >> M: 0400 12 11 16 ----- End message from Dan Mahoney <[hidden email]> ----- -- Simon Wilson M: 0400 12 11 16 |
Replied inline and snipped. Apologies if my mail.app gets this wrong.
> On Apr 1, 2021, at 7:49 PM, Simon Wilson <[hidden email]> wrote: > > ----- Message from Dan Mahoney <[hidden email]> --------- > Date: Thu, 1 Apr 2021 16:19:05 -0700 > From: Dan Mahoney <[hidden email]> > Subject: Re: Milters and policy > To: [hidden email] > Cc: [hidden email] > > >>> On Mar 31, 2021, at 18:23, Simon Wilson <[hidden email]> wrote: >>> >>> >>>> >>>>> ...if multiple milters are called are they run in order specified? >>>>> >>>>> smtpd_milters = inet:127.0.0.1:8891,inet:127.0.0.1:8893 >>>> >>>> yes >>>> >>>>> I.e. in the example above if OpenDMARC is to see and trust an >>>>> already-run OpenDKIM Authentication-Results header is the order of >>>>> specifying the milters important? >>>> >>>> yes opendkim need to run before opendmarc, and if you have openarc place that before opendkim, it can be messy if opendmarc checks openarc results, remeber it also need to trust AR headers to be considered good info >>>> >>>> but i do not use milters self, only do all i need with fuglu >>> >>> Thanks again Benny. I have policyd-spf set to insert an AR header, and OpenDMARC set to trust the Authserv-Id added in Authentication-Results headers by policyd-spf and OpenDKIM. All working nicely and good to understand the sequence. >> >> Please read CVE-2019-20790, and tell me you’ve found a way to tell PyPolicyd not to trust the SMTP HELO to generate a passing AR header. >> >> -Dan >> > > In the interests of open disclosure of your interests, I assume [hidden email] = https://github.com/thegushi = OpenDMARC developer? Calling me a developer is a bit strong. I’m a fairly new member of the team, mostly trying to do issue wrangling and patch management, and maybe get our mailing lists converted to something that isn’t dependent on an EOL python, but I don’t/didn’t write most of the code. I’m mainly a sysadmin and network operator. I am also (coincidentally) the maintainer for the FreeBSD opendmarc port, which might explain this journey. > This is possibly off-topic for the Postfix list... maybe not. …with tongue in cheek, I’ll take all the discussion about mail filtering over any about political correctness that’s happened this year. That said, if people feel this is off topic, nudge me privately and I’ll take a hint. > Re the risk from the CVE to my setup... > > I run policyd-spf as a postfix check_policy with reject on fail (on both HELO and MAILFROM), and assuming a mail gets past that (99% do), I then use that Pass along with OpenDKIM and OpenDMARC to contribute to Spamassassin scoring. My DMARC Spamassassin rules do not apply a -ve on a pass, only a +ve on a fail. > > The impact of a false pass from DMARC (particularly as our Webmail system - Horde - does not show any added trust for a dmarc pass) would be failure to apply a negative Spamassassin score from a the missed DMARC fail. With my mail setup and users the impact of that is probably manageable... but agreed it is not ideal. > > What concerns me as much as anything is that each of the apps' devs in question (pypolicyd-spf and opendmarc) are each pointing at each other :-/ > > https://bugs.launchpad.net/pypolicyd-spf/+bug/1838816/comments/4: > "my belief that the issue here is a DMARC processor failing to do alignment validation correctly" > > https://github.com/trusteddomainproject/OpenDMARC/issues/49#issuecomment-802242666 > "Honestly, this CVE seems more to belong to py-policyd than OpenDMARC." > > What would be nice would be if the two of you worked together on coming up with a fix... The upcoming 1.4.1 will have a more detailed explanation of the CVE in question as we go over the decisions that we made in taking action on this. My logic in writing up the CVE summary was: OpenDMARC is following the protocols as designed. If an earlier milter in the chain says SPF passed, it doesn’t feel right to pick that apart and say “but did it really?” The CVE was not “All SPF milters in all configurations allow failed authentication with opendmarc" — py-policyd was one called out specifically. That says something to me. > Anyways... > > I see two possible workarounds (not fixes). > > 1. Setting pypolicyd to HELO_Reject = No_Check. RFC7208 indicates that MAILFROM and HELO are both equally valid for an SPF result, *BUT* the vast majority of my SPF checks trigger pass or fail on MAILFROM (I've had 3 spf HELO passes in 10 days on HELO, thousands on MAILFROM). Testing pypolicyd-spf with HELO_reject = No_Check results in spf=none for those. Removing the HELO check means that OpenDMARC can assume any spf result it is given is based on MAILFROM. RFC7489 Section 4.1: "DMARC uses the result of SPF authentication of the MAIL FROM identity.” If we’re processing SPF ourselves, this is true. (The SPF RFC calls HELO checking optional). If we’re parsing an earlier added header (perhaps added by a border MX), we prioritize spf=pass over other decisions. (Perhaps this is wrong to do). With regard to OpenDMARC, we *could* add a check on an earlier SPF header that checks *ONLY* the mail-from identity in a received-spf header. This might be a better response to the CVE for future code, but at the very least right now a workaround and a statement is warranted. In turn, that could lead users to point at an SPF=pass in a previous A/R or received-spf header, and complain that we’re still rejecting. It could also lead OpenDMARC to add its own SPF A/R header with a different result than a previous one, which could greater complicate things down the chain. Which header does a downstream filter (say, Spamd) believe? > 2. Tell OpenDMARC to *NOT* trust any existing spf result and do its own. I.e. SPFIgnoreResults true. This obviously doubles SPF processing time, and relegates pypolicyd-spf to purely an inbound policy reject check. If one is not using pypolicyd to reject then this would be pointless, and it could be removed from the stack. Rejecting based on an SPF policy such as -all is carefully cautioned when used with DMARC (RFC7489 10.1). Since SPF is broken by pretty much every mailing list, and mailing lists are not SPF aware (but some ARE dmarc aware), using py-policyd to reject is probably not a great idea anyway, since as far as I know py-policyd doesn’t know how to check if a _dmarc record also exists. Our advice to the administrators is to carefully evaluate the behavior of this software — be aware that this is a failure mode, and act accordingly. I don’t use py-policyd, so I don’t know what else it can be used to do (for example, if it’s a general purpose wrapper like Amavis is). I don’t feel that we should be writing documentation or suggesting specific configuration knobs for software we didn’t put out. The CVE response is visible in the SECURITY folder in our github on the “develop” branch. This specific callout will probably also be in the RELEASE NOTES, which we’re still writing. Stay safe out there, -Dan > > Thoughts? > >> >>> >>> Simon. >>> >>> -- >>> Simon Wilson >>> M: 0400 12 11 16 > > > ----- End message from Dan Mahoney <[hidden email]> ----- > > > > -- > Simon Wilson > M: 0400 12 11 16 |
>>> Please read CVE-2019-20790, and tell me you’ve found a way to tell
>>> PyPolicyd not to trust the SMTP HELO to generate a passing AR >>> header. > >> This is possibly off-topic for the Postfix list... maybe not. > > …with tongue in cheek, I’ll take all the discussion about mail > filtering over any about political correctness that’s happened this > year. That said, if people feel this is off topic, nudge me > privately and I’ll take a hint. Ditto - perhaps some of these comments are better placed at https://github.com/trusteddomainproject/OpenDMARC/issues/49 >> Re the risk from the CVE to my setup... >> >> I run policyd-spf as a postfix check_policy with reject on fail (on >> both HELO and MAILFROM), and assuming a mail gets past that (99% >> do), I then use that Pass along with OpenDKIM and OpenDMARC to >> contribute to Spamassassin scoring. My DMARC Spamassassin rules do >> not apply a -ve on a pass, only a +ve on a fail. >> >> The impact of a false pass from DMARC (particularly as our Webmail >> system - Horde - does not show any added trust for a dmarc pass) >> would be failure to apply a negative Spamassassin score from a the >> missed DMARC fail. With my mail setup and users the impact of that >> is probably manageable... but agreed it is not ideal. >> >> What concerns me as much as anything is that each of the apps' devs >> in question (pypolicyd-spf and opendmarc) are each pointing at each >> other :-/ >> >> https://bugs.launchpad.net/pypolicyd-spf/+bug/1838816/comments/4: >> "my belief that the issue here is a DMARC processor failing to do >> alignment validation correctly" >> >> https://github.com/trusteddomainproject/OpenDMARC/issues/49#issuecomment-802242666 >> "Honestly, this CVE seems more to belong to py-policyd than OpenDMARC." >> >> What would be nice would be if the two of you worked together on >> coming up with a fix... > > The upcoming 1.4.1 will have a more detailed explanation of the CVE > in question as we go over the decisions that we made in taking > action on this. > > My logic in writing up the CVE summary was: OpenDMARC is following > the protocols as designed. If an earlier milter in the chain says > SPF passed, it doesn’t feel right to pick that apart and say “but > did it really?” This is (IMO) flawed reasoning. Hear me out... :) The *sole* scope of pypolicyd-spf is *SPF* validation at the SMTP transaction point. RFC7208 recommends that SPF verifiers check both HELO and MAIL FROM (2.3), and pypolicyd-spf provides users with the ability to choose whether to do MAIL FROM only or also HELO. Out of the box it aligns with RFC 7208's recommended approach, checking both. There is nothing in the SPF RFC which says *for the purposes of SPF* that either HELO or MAIL FROM validation is more or less valid than the other. As defined in SPF, both are valid. We know SPF is not perfect, which is why it has been extended and added to by things like DMARC... but remember this is at the moment *solely in context of an SPF policy agent*. Pypolicyd-spf then tags what has driven the result for later use: E.g. Apr 3 11:19:23 emp87 policyd-spf[1336326]: prepend Authentication-Results: mail.simonandkate.net; spf=pass (mailfrom) Apr 2 12:32:51 emp87 policyd-spf[1255235]: prepend Authentication-Results: mail.simonandkate.net; spf=pass (helo) Whether or not MTAs upstream have enforced matches of hostname to EHLO, Pypolicyd-spf is meeting its defined brief. Whether or not you think "trusting HELO is insane" it is clearly a valid interpretation of the SPF RFC for an SPY policy agent to assign a pass based on HELO. It is *not* "a bad authentication results header" if pypolicyd-spf tags as such (quotes from https://github.com/trusteddomainproject/OpenDMARC/issues/49#issuecomment-803634646, https://github.com/trusteddomainproject/OpenDMARC/issues/49#issuecomment-800047724). >> 1. Setting pypolicyd to HELO_Reject = No_Check. RFC7208 indicates >> that MAILFROM and HELO are both equally valid for an SPF result, >> *BUT* the vast majority of my SPF checks trigger pass or fail on >> MAILFROM (I've had 3 spf HELO passes in 10 days on HELO, thousands >> on MAILFROM). Testing pypolicyd-spf with HELO_reject = No_Check >> results in spf=none for those. Removing the HELO check means that >> OpenDMARC can assume any spf result it is given is based on MAILFROM. > > RFC7489 Section 4.1: "DMARC uses the result of SPF authentication > of the MAIL FROM identity.” > > If we’re processing SPF ourselves, this is true. (The SPF RFC calls > HELO checking optional). If we’re parsing an earlier added header > (perhaps added by a border MX), we prioritize spf=pass over other > decisions. (Perhaps this is wrong to do). > > With regard to OpenDMARC, we *could* add a check on an earlier SPF > header that checks *ONLY* the mail-from identity in a received-spf > header. This might be a better response to the CVE for future code, > but at the very least right now a workaround and a statement is > warranted. So now we come to DMARC. The DMARC RFC7489 says at 3.1 about SPF: "while [SPF] can authenticate either the domain that appears in the RFC5321.MailFrom (MAIL FROM) portion of [SMTP] or the RFC5321.EHLO/ HELO domain, or both" ...acknowledging that a valid SPF pass can be based on HELO. It then says (4.1) that DMARC *must only use SPF MAIL FROM* authentication: "DMARC uses the result of SPF authentication of the MAIL FROM identity" pypolicyd-spf is giving OpenDMARC the necessary information to check whether this is achievable. Look at my example log entries as noted above with the prepend headers: spf=pass (mailfrom) spf=pass (helo) OpenDMARC has the information needed to make an informed decision on whether the SPF pass which has been made earlier can actually be used in alignment with the DMARC RFC (i.e. based on MAIL FROM) or should be ignored (i.e. based on HELO). If OpenDMARC stops parsing at "spf=pass" how is that an issue with anything other than OpenDMARC? The DMARC RFC *explicitly* says that DMARC must only use an SPF authentication of MAIL FROM - It does not say that DMARC should trust an spf=pass. Your comment: "we *could* add a check on an earlier SPF header that checks *ONLY* the mail-from identity in a received-spf header" strikes me as being the sensible fix. In fact, if OpenDMARC is *NOT* checking against only an SPF MAILFROM pass, perhaps you can enlighten me on how it is compliant with RFC7489 4.1? > In turn, that could lead users to point at an SPF=pass in a previous > A/R or received-spf header, and complain that we’re still > rejecting. It could also lead OpenDMARC to add its own SPF A/R > header with a different result than a previous one, which could > greater complicate things down the chain. Which header does a > downstream filter (say, Spamd) believe? Again - spf=pass is not the issue. > Rejecting based on an SPF policy such as -all is carefully cautioned > when used with DMARC (RFC7489 10.1). Since SPF is broken by pretty > much every mailing list, and mailing lists are not SPF aware (but > some ARE dmarc aware), using py-policyd to reject is probably not a > great idea anyway, since as far as I know py-policyd doesn’t know > how to check if a _dmarc record also exists. Not true. I currently reject SPF on fail, am on dozens of mailing lists without issue (I should say without *SPF* issues... ignoring issues like the OpenDMARC mailing list's use of deprecated TLS protocols). I usually get spf=none from those. I currently have only 1 dumb domain in my SPF skip-check whitelist (I've contacted them, no change). On my small server this results in (after extensive postscreen activity dropping about 90% of connection attempts) typically 2 or 3 SPF rejects a day (out of 300 to 500 emails. Of those, maybe 1 every three or four weeks is a false positive. Yes I could accept and pass further down the line for evaluation and e.g. DMARC tagging - I choose not to. Your interpretation of RFC7489 10.1 is also flawed (again IMO)... "Some receiver architectures might implement SPF in advance of any DMARC operations. This means that a "-" prefix on a sender's SPF mechanism, such as "-all", could cause that rejection to go into effect early in handling, causing message rejection before any DMARC processing takes place. Operators choosing to use "-all" should be aware of this." That places the onus on domain owners, not receivers. It acknowledges that some receivers do SPF before DMARC and that may result in rejection before DMARC - it then cautions Operators to be aware of that risk. It is entirely valid under the SPF RFC for a receiver to reject messages based on an SPF Fail (RFC7208 G.2)... and I choose to do so before I get to DMARC. > Our advice to the administrators is to carefully evaluate the > behavior of this software — be aware that this is a failure mode, > and act accordingly. > > I don’t use py-policyd, so I don’t know what else it can be used to > do (for example, if it’s a general purpose wrapper like Amavis is). > I don’t feel that we should be writing documentation or suggesting > specific configuration knobs for software we didn’t put out. > > The CVE response is visible in the SECURITY folder in our github on > the “develop” branch. This specific callout will probably also be > in the RELEASE NOTES, which we’re still writing. > Fundamentally I agree with Scott Kitterman here (https://bugs.launchpad.net/pypolicyd-spf/+bug/1838816/comments/3): "If you look at https://tools.ietf.org/html/rfc7208#section-4.1 you can see that both HELO and Mail From are treated as first class inputs to check_host(). From a specification perspective, the result needs to consider what identity it relates to, which is why I think ***a DMARC processor that assumes any reported SPF result relates to the Mail From of the message is buggy***. Scott K" (***emphasis added***) Simon -- Simon Wilson M: 0400 12 11 16 |
On Sat, 3 Apr 2021, Simon Wilson wrote:
>>>> Please read CVE-2019-20790, and tell me you’ve found a way to tell >>>> PyPolicyd not to trust the SMTP HELO to generate a passing AR header. >> >>> This is possibly off-topic for the Postfix list... maybe not. >> >> …with tongue in cheek, I’ll take all the discussion about mail filtering >> over any about political correctness that’s happened this year. That said, >> if people feel this is off topic, nudge me privately and I’ll take a hint. > > Ditto - perhaps some of these comments are better placed at > https://github.com/trusteddomainproject/OpenDMARC/issues/49 I really would like to make OpenDMARC do the fully correct thing. My current reading of the various specs is that there's no hard requirement that the requisite filters *actually put enough info into the headers* to do such a thing. Apologies for the noise here. It may not fully be over, but it's my hope that the net result is good software for the internet at large. -Dan -- --------Dan Mahoney-------- Techie, Sysadmin, WebGeek Gushi on efnet/undernet IRC FB: fb.com/DanielMahoneyIV LI: linkedin.com/in/gushi Site: http://www.gushi.org --------------------------- |
Free forum by Nabble | Edit this page |