Saturday, March 14, 2009

SMTP relaying from OS/X

I like to relay my laptop's mail through a personal mail relay, so that no matter where I send mail from, it has a tunnel to a mail server that can send it on to the outside world.  I previously posted the details for doing this on a Debian laptop.  Here's what I have found for an OS/X laptop.

There are two things that I have found that should be changed to use the external relay: Mail.app and Postfix. Mail.app, the built-in mail reader, can be configured through its preferences GUI.  I don't remember all the individual steps, but I remember it being straightforward.  The first time you send email, you'll be warned about an untrusted certificate.  In that dialog, you can specify both that the certificate is good for sending email through, and that the certificate is in general legitimate.

The other thing that might need modifying, depending on what you do with your laptop, is Postfix.  From some web searching, I found this page by Michael Prokop.  In short, the magic contents of /etc/postfix/main.cf are as follows:

relayhost = mail.vc-graz.ac.at
smtp_use_tls = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/smtp_auth
smtp_sasl_security_options = noanonymous

Note that if your mail relay runs on port 26, you can put the port number on the relayhost line, like this:

relayhost = mail.vc-graz.ac.at:26

You then have to set up /etc/postfix/smtp_auth with your client password information.

Overall, it takes a few minutes to set it all up, but you end up with your laptop being able to send email from pretty much any Internet connection.  I'm posting it here in case anyone else finds it convenient.

Friday, March 13, 2009

Ivan Krstic on security-friendly languages

Ivan Krstic writes:
Now, while I’m already grossly overgeneralizing, I think the first group is almost useless, the second group is almost irrelevant, and the third group is absolutely horrible at explaining what the hell they’re talking about.
He and the commenters then give some good introductory links.

Wednesday, March 4, 2009

Installing top-level code with JavaScript's eval

JavaScript is wonderfully dynamic, so it is odd that its eval function is so unportable.  I already knew that it was tricky if not impossible to use eval to install code in an arbitrary nested scope.  Today I learned that even the simple case of installing code into the global scope is different on each browser. Here's what I found after some digging around on the web and some experimentation.

First, there are a lot of web pages discussing this topic.  Here's one of the first ones I read, that tipped me off that there is a well-known problem:

http://piecesofrakesh.blogspot.com/2008/10/understanding-eval-scope-spoiler-its.html

The following page also discusses the problem, but has a really good collection of comments:
UPDATE: Prototype has gone through the same issue, and come up with similar conclusions as mine.  Here is a page with all the bike shedding:



Based on reading these and on tinkering on different web browsers, here are some techniques that look interesting:
  1. window.eval, what I tried to begin with
  2. window.eval, but with a with() clause around it.  Some people report better luck this way.
  3. window.execScript, a variant of window.eval
  4. window.setTimeout
  5. adding a script tag to the document

What I did in each case was try to use the technique to define a function foo() at the global scope, and then try to call it.  I tested these browsers, which I happen to have handy:
  1. Safari/Mac 3.1.1
  2. Firefox/Mac 3.0.6
  3. Firefox/Linux 2.0.0.20
  4. Firefox/Windows 3.0.3
  5. IE 6.0.2900.xpsp_sp3_gdr.080814-1236 updated to SP3
  6. Chrome 1.0.154.48

Here are the browsers where each technique works.  I lump together the Firefoxes because they turn out to behave the same on all platforms:
  1. window.eval: FF
  2. window.eval with with: FF
  3. window.execScript: IE, Chrome
  4. window.setTimeout: Chrome, FF, Safari
  5. script tag: IE, Chrome, FF, Safari

Conclusions

  1. The window.execScript function is available on IE and Chrome, and when present it does the right thing.
  2. The window.eval function only works as desired on Firefox.
  3. Adding a with(window) around the window.eval does make a difference, but I couldn't get it to do precisely what is needed for GWT.  In particular, GWT does not have a bunch of "var func1,func2, func3" declarations up front, but such vars are assumed in some of the other web pages I read.
  4. I could not find a synchronous solution for Safari.  Instead, setTimeout and script tags work, but they won't load the code until a few milliseconds have gone by.
  5. Script tags work on all browsers.
  6. Surprisingly, I couldn't get setTimeout to work on IE.  From some web browsing, it looks like the setTimeout callback might run in the wrong scope, but I didn't investigate far.  On IE, execScript is a better solution for the present problem.
Based on these, the following chunk of code is one portable way to install code on any of the major browsers.  It uses execScript if it's available, and otherwise it adds a script tag.
if (window.execScript) {
  window.execScript(script)
} else {
  var tag = document.createElement("script")
  tag.type = "text/javascript"
  tag.text = script
  document.getElementsByTagName("head").item(0).appendChild(tag)
}

The Code
Here is the code for the above examples, for anyone who wants to know the details and/or to try it for themselves.

The wrapper script is as follows:
function installFoo() {
  var script = "function foo() { alert('hi') }"
  // varying part
}
installFoo()
window.foo()

For the versions that install the code asynchronously (setTimeout or script tags), I changed the window.foo() line to be:
window.setTimeout(function() { window.foo() }, 100)


The "varying part" is as follows for each way to load the code.  Note that some of them include a gratuitous reassignment of window to $w; that's how I first ran the test and I don't want to go back and redo all of those.

// window.eval
window.eval(script)

// window.execScript
window.execScript(script)

// window.eval with a with
var $w = window
with($w) { $w.eval(script) }

// setTimeout
window.setTimeout(script, 0)

// script tag
var tag = document.createElement("script")
tag.type = "text/javascript"
tag.text = script
document.getElementsByTagName("head").item(0).appendChild(tag)