You almost have it:
ext = X509.new_extension('1.2.3.4',
'ASN1:UTF8String:Some random data')
# If required: ext.set_critical(1)
cert.add_ext(ext)
It will appear in the OpenSSL dump:
1a:91:ca:bf:aa:ba:3b:49:57
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:foobar.example.com
1.2.3.4:
..Some random data
Signature Algorithm: sha1WithRSAEncryption
18:24:4c:42:fe:7c:71:a6:58:ed:be:9d:2e:9e:ea:a7:80:0f:
Unfortunately, M2Crypto has a problem retrieving custom extensions unless they were to be registered first, and those functions aren't currently exposed through M2Crypto. The name and value will come back as "UNDEF" and "None", respectively.