#!/usr/bin/python
#
#  Developer certificate request generation tool
#  Copyright (C) 2007 - 2009 Martin Storsjo
#
#  This software is provided 'as-is', without any express or implied
#  warranty.  In no event will the authors be held liable for any damages
#  arising from the use of this software.
#
#  Permission is granted to anyone to use this software for any purpose,
#  including commercial applications, and to alter it and redistribute it
#  freely, subject to the following restrictions:
#
#  1. The origin of this software must not be misrepresented; you must not
#     claim that you wrote the original software. If you use this software
#     in a product, an acknowledgment in the product documentation would be
#     appreciated but is not required.
#  2. Altered source versions must be plainly marked as such, and must not be
#     misrepresented as being the original software.
#  3. This notice may not be removed or altered from any source distribution.

import sys
import getopt
import tempfile
import commands
import struct
import os

argv = sys.argv[1:]

short_opts = 'c:k:i:o:t:h'
long_opts = [ 'cert=', 'key=', 'out=', 'imei=', 'conf=', 'help' ]
args = getopt.gnu_getopt(argv, short_opts, long_opts)
opts = dict(args[0])
pargs = args[1]

cert = opts.get('--cert', opts.get('-c', None))
key = opts.get('--key', opts.get('-k', None))
out = opts.get('--out', opts.get('-o', None))
imei = opts.get('--imei', opts.get('-i', None))
help = opts.get('--help', opts.get('-h', None))
confName = opts.get('--conf', None)

if help != None or cert == None or key == None or out == None or imei == None:
	print "%s --cert mycert.cer --key mykey.key --out request.csr --imei imeifile [--help] [--conf request.cnf]" % (sys.argv[0])
	sys.exit(0)

removeConf = False

if confName == None:
	tuple = tempfile.mkstemp(suffix='.cnf')
	conf = os.fdopen(tuple[0], 'w')
	confName = tuple[1]
	removeConf = True
else:
	conf = file(confName, 'w')

conf.write('''[req]
default_bits=1024
distinguished_name=req_distinguished_name
prompt=no
req_extensions=extend
[req_distinguished_name]
''')

issuer = commands.getoutput('openssl x509 -in %s -text | grep Issuer:' % cert)
subject = commands.getoutput('openssl x509 -in %s -text | grep Subject: | sed "s/Subject: //"' % cert)
subjectArray = subject.strip().split(', ')
for s in subjectArray:
	conf.write(s + '\n')

imeis = []
try:
	imeifile = file(imei, 'r')
	for l in imeifile.readlines():
		l = l.strip()
		if len(l) == 0:
			continue
		if l[0] == '#':
			continue
		line = l.split()
		imeis.append(line[0])
	imeifile.close()
except:
	imeis.append(imei)

conf.write('[extend]\n')
conf.write('1.2.826.0.1.1796587.1.1.1.1=critical,DER::')
imeibuf = ''
for i in imeis:
	imeibuf += '%c' % 0x0c
	imeibuf += '%c' % len(i)
	imeibuf += i
l = len(imeibuf)
prefix = '%c' % 0x30
if l > 255:
	prefix += ('%c' % 0x82) + struct.pack('!H', l)
elif l > 127:
	prefix += '%c%c' % (0x81, l)
else:
	prefix += '%c' % l
content = prefix + imeibuf
for c in content:
	conf.write('%02x' % ord(c))
conf.write('\n')

capinfo = [
	('TCB',             0),
	('CommDD',          1),
	('PowerMgmt',       2),
	('MultimediaDD',    3),
	('ReadDeviceData',  4),
	('WriteDeviceData', 5),
	('DRM',             6),
	('TrustedUI',       7),
	('ProtServ',        8),
	('DiskAdmin',       9),
	('NetworkControl',  10),
	('AllFiles',        11),
	('SwEvent',         12),
	('NetworkServices', 13),
	('LocalServices',   14),
	('ReadUserData',    15),
	('WriteUserData',   16),
	('Location',        17),
	('SurroundingsDD',  18),
	('UserEnvironment', 19)
]
capnametonum = dict([(cname.lower(), cnum) for cname, cnum in capinfo])

common = ['PowerMgmt', 'ReadDeviceData', 'WriteDeviceData', 'TrustedUI', 'ProtServ', 'SwEvent', 'NetworkServices', 'LocalServices', 'ReadUserData', 'WriteUserData', 'Location', 'SurroundingsDD', 'UserEnvironment']
extra = ['CommDD', 'MultimediaDD', 'DiskAdmin', 'NetworkControl']

caps = common
if 'TrustCenter' in issuer:
	caps.extend(extra)

capmask = 0
for c in caps:
	capmask |= 1 << (31 - capnametonum[c.lower()])

conf.write('1.2.826.0.1.1796587.1.1.1.6=critical,DER::')
data = ''
data += '%c' % 0x03
data += '%c' % 0x09
data += '%c' % 0x00
data += struct.pack('>LL', capmask, 0)
for c in data:
	conf.write('%02x' % ord(c))
conf.write('\n')

conf.close()

print commands.getoutput('openssl req -new -key %s -config %s > %s' % (key, confName, out))
if 'TrustCenter' in issuer:
	commands.getoutput('openssl x509 -in %s -outform PEM >> %s' % (cert, out))


if removeConf:
	os.unlink(confName)



