I'm not sure about the main client, but here is some ghetto PHP code that works. I've used it to create a bunch of multisig p2sh addresses.
function createmultisig($nReq,$keys,$sortkeys=TRUE){
$debug=FALSE;
// I always sort keys so that I end up with a canonical p2sh address for any given set of keys and parameters
// if you are testing this against another implementation, disable the sorting, or put them in sorted order before calling the other code
if($sortkeys)sort($keys,SORT_STRING);
// P2SH multisig in bitcoin requires between 2 and 16 (inclusive) keys
// this appears mostly to be because of the single-byte PUSH_x opcodes, 0x52 to 0x60
if($nReq<2 OR $nReq>16 OR $nReq>count($keys))return FALSE;
// the structure of P2SH multisig is very simple. This short block assembles the redeemscript
$rs=chr(0x50+$nReq);
while(list($key,$val)=each($keys)){
$bpk=hex2bin($val);
$rs.=chr(strlen($bpk)).$bpk;
}
$rs.=chr(0x50+count($keys));
$rs.=chr(0xae);
// this block then turns the redeem script into an address.
// the debug lines allow easy verification of each step to compare with published examples
if($debug)echo "In: ".$rs."\n";
$h=hash("sha256",$rs,TRUE);
if($debug)echo "H: ".bin2hex($h)."\n";
$h2=hash("ripemd160",$h,TRUE);
if($debug)echo "H2: ".bin2hex($h2)."\n";
$h3="\x05".$h2;
if($debug)echo "H3: ".bin2hex($h3)."\n";
$h4=hash("sha256",$h3,TRUE);
if($debug)echo "H4: ".bin2hex($h4)."\n";
$h5=hash("sha256",$h4,TRUE);
if($debug)echo "H5: ".bin2hex($h5)."\n";
$chk=substr($h5,0,4);
if($debug)echo "Chk: ".bin2hex($chk)."\n";
$addr_bin=$h3.$chk;
if($debug)echo "addr: ".bin2hex($addr_bin)."\n";
$addr=encodeBase58($addr_bin);
if($debug)echo $addr."\n";
return array("redeemScript"=>bin2hex($rs),"address"=>$addr);
}