PageRenderTime 57ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/IronPython.Modules/_ssl.cs

http://github.com/IronLanguages/main
C# | 749 lines | 579 code | 126 blank | 44 comment | 131 complexity | ecf82d1e3054f2d48be39c413bca12c5 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if FEATURE_FULL_NET
  16. using System;
  17. using System.Collections.Generic;
  18. using System.IO;
  19. using System.Linq;
  20. using System.Runtime.CompilerServices;
  21. using System.Runtime.InteropServices;
  22. using System.Security.Cryptography;
  23. using System.Security.Cryptography.X509Certificates;
  24. using System.Text;
  25. using Microsoft.Scripting.Runtime;
  26. using Microsoft.Scripting.Utils;
  27. using IronPython.Runtime;
  28. using IronPython.Runtime.Exceptions;
  29. using IronPython.Runtime.Operations;
  30. using IronPython.Runtime.Types;
  31. [assembly: PythonModule("_ssl", typeof(IronPython.Modules.PythonSsl))]
  32. namespace IronPython.Modules {
  33. internal class Asn1Object {
  34. public Asn1Object(string shortName, string longName, int nid, byte[] oid) {
  35. ShortName = shortName;
  36. LongName = longName;
  37. NID = nid;
  38. OID = oid;
  39. #if !CLR2
  40. OIDString = string.Join(".", OID);
  41. #else
  42. StringBuilder buf = new StringBuilder();
  43. foreach(byte b in oid) {
  44. buf.AppendFormat("{0}.");
  45. }
  46. OIDString = buf.ToString().Trim('.');
  47. #endif
  48. }
  49. public string ShortName {
  50. get; set;
  51. }
  52. public string LongName {
  53. get; set;
  54. }
  55. public int NID {
  56. get; set;
  57. }
  58. public byte[] OID {
  59. get; set;
  60. }
  61. public string OIDString {
  62. get;
  63. }
  64. public PythonTuple ToTuple() {
  65. return PythonTuple.MakeTuple(NID, ShortName, LongName, OIDString);
  66. }
  67. }
  68. public static class PythonSsl {
  69. public const string __doc__ = "Implementation module for SSL socket operations. See the socket module\nfor documentation.";
  70. public const int OPENSSL_VERSION_NUMBER = 9437184;
  71. public static readonly PythonTuple OPENSSL_VERSION_INFO = PythonTuple.MakeTuple(0, 0, 0, 0, 0);
  72. public static readonly object _OPENSSL_API_VERSION = OPENSSL_VERSION_INFO;
  73. public const string OPENSSL_VERSION = "OpenSSL 0.0.0 (.NET SSL)";
  74. private static List<Asn1Object> _asn1Objects = new List<Asn1Object>();
  75. static PythonSsl() {
  76. _asn1Objects.AddRange(new Asn1Object[] {
  77. new Asn1Object("serverAuth", "TLS Web Server Authentication", 129, new byte[] { 1, 3, 6, 1 ,5, 5, 7, 3, 1 }),
  78. new Asn1Object("clientAuth", "TLS Web Client Authentication", 130, new byte[] { 1, 3, 6, 1 ,5, 5, 7, 3, 2 }),
  79. });
  80. }
  81. [SpecialName]
  82. public static void PerformModuleReload(PythonContext/*!*/ context, PythonDictionary/*!*/ dict) {
  83. var socket = context.GetBuiltinModule("socket");
  84. var socketError = PythonSocket.GetSocketError(context, socket.__dict__);
  85. var sslError = context.EnsureModuleException("SSLError", socketError, dict, "SSLError", "ssl");
  86. context.EnsureModuleException("SSLZeroReturnError", sslError, dict, "SSLZeroReturnError", "ssl");
  87. context.EnsureModuleException("SSLWantWriteError", sslError, dict, "SSLWantWriteError", "ssl");
  88. context.EnsureModuleException("SSLSyscallError", sslError, dict, "SSLSyscallError", "ssl");
  89. context.EnsureModuleException("SSLEOFError", sslError, dict, "SSLEOFError", "ssl");
  90. context.EnsureModuleException("SSLWantReadError", sslError, dict, "SSLWantReadError", "ssl");
  91. }
  92. #region Stubs for RAND functions
  93. // The RAND_ functions are effectively no-ops, as the BCL draws on system sources
  94. // for cryptographically-strong randomness and doesn't need (or accept) user input
  95. public static void RAND_add(object buf, double entropy) {
  96. if (buf == null) {
  97. throw PythonOps.TypeError("must be string or read-only buffer, not None");
  98. } else if (!(buf is string) && !(buf is PythonBuffer)) {
  99. throw PythonOps.TypeError("must be string or read-only buffer, not {0}", PythonOps.GetPythonTypeName(buf));
  100. }
  101. }
  102. public static int RAND_status() {
  103. return 1; // always ready
  104. }
  105. #endregion
  106. #region SSLContext
  107. [PythonType]
  108. public class _SSLContext {
  109. private X509Certificate2Collection _cert_store = new X509Certificate2Collection();
  110. private string _cafile;
  111. private int _verify_mode = SSL_VERIFY_NONE;
  112. public _SSLContext(CodeContext context, [DefaultParameterValue(PROTOCOL_SSLv23)] int protocol) {
  113. if (protocol != PROTOCOL_SSLv2 && protocol != PROTOCOL_SSLv23 && protocol != PROTOCOL_SSLv3 &&
  114. protocol != PROTOCOL_TLSv1 && protocol != PROTOCOL_TLSv1_1 && protocol != PROTOCOL_TLSv1_2) {
  115. throw PythonOps.ValueError("invalid protocol version");
  116. }
  117. this.protocol = protocol;
  118. if (protocol != PROTOCOL_SSLv2)
  119. options |= OP_NO_SSLv2;
  120. if (protocol != PROTOCOL_SSLv3)
  121. options |= OP_NO_SSLv3;
  122. verify_mode = SSL_VERIFY_NONE;
  123. check_hostname = false;
  124. }
  125. public void set_ciphers(CodeContext context, string ciphers) {
  126. }
  127. public int options {
  128. get; set;
  129. }
  130. public int verify_mode {
  131. get {
  132. return _verify_mode;
  133. }
  134. set {
  135. if(_verify_mode != CERT_NONE && _verify_mode != CERT_OPTIONAL && _verify_mode != CERT_REQUIRED) {
  136. throw PythonOps.ValueError("invalid value for verify_mode");
  137. }
  138. _verify_mode = value;
  139. }
  140. }
  141. public int protocol {
  142. get; set;
  143. }
  144. public bool check_hostname {
  145. get; set;
  146. }
  147. public void set_default_verify_paths(CodeContext context) {
  148. }
  149. public void load_cert_chain(string certfile, [DefaultParameterValue(null)] string keyfile, [DefaultParameterValue(null)] object password) {
  150. }
  151. public void load_verify_locations(CodeContext context, [DefaultParameterValue(null)] string cafile, [DefaultParameterValue(null)] string capath, [DefaultParameterValue(null)] object cadata) {
  152. if(cafile == null && capath == null && cadata == null) {
  153. throw PythonOps.TypeError("cafile, capath and cadata cannot be all omitted");
  154. }
  155. if(cafile != null) {
  156. _cert_store.Add(ReadCertificate(context, cafile));
  157. _cafile = cafile;
  158. }
  159. if(capath != null) {
  160. }
  161. if(cadata != null) {
  162. var cabuf = cadata as IBufferProtocol;
  163. if (cabuf != null) {
  164. int pos = 0;
  165. byte[] contents = cabuf.ToBytes(0, null).ToByteArray();
  166. while(pos < contents.Length) {
  167. byte[] curr = new byte[contents.Length - pos];
  168. Array.Copy(contents, pos, curr, 0, contents.Length - pos);
  169. var cert = new X509Certificate2(curr);
  170. _cert_store.Add(cert);
  171. pos += cert.GetRawCertData().Length;
  172. }
  173. }
  174. }
  175. }
  176. public object _wrap_socket(CodeContext context, [DefaultParameterValue(null)] PythonSocket.socket sock, [DefaultParameterValue(false)] bool server_side, [DefaultParameterValue(null)] string server_hostname, [DefaultParameterValue(null)] object ssl_sock) {
  177. return new PythonSocket.ssl(context, sock, server_side, null, _cafile, verify_mode, protocol | options, null, _cert_store);
  178. }
  179. }
  180. #endregion
  181. public static PythonType SSLType = DynamicHelpers.GetPythonTypeFromType(typeof(PythonSocket.ssl));
  182. public static PythonSocket.ssl sslwrap(
  183. CodeContext context,
  184. PythonSocket.socket socket,
  185. bool server_side,
  186. [DefaultParameterValue(null)] string keyfile,
  187. [DefaultParameterValue(null)] string certfile,
  188. [DefaultParameterValue(PythonSsl.CERT_NONE)]int certs_mode,
  189. [DefaultParameterValue(PythonSsl.PROTOCOL_SSLv23 | PythonSsl.OP_NO_SSLv2 | PythonSsl.OP_NO_SSLv3)]int protocol,
  190. [DefaultParameterValue(null)]string cacertsfile,
  191. [DefaultParameterValue(null)]object ciphers) {
  192. return new PythonSocket.ssl(
  193. context,
  194. socket,
  195. server_side,
  196. keyfile,
  197. certfile,
  198. certs_mode,
  199. protocol,
  200. cacertsfile,
  201. null
  202. );
  203. }
  204. public static object txt2obj(CodeContext context, string txt, [DefaultParameterValue(false)] object name) {
  205. bool nam = PythonOps.IsTrue(name); // if true, we also look at short name and long name
  206. Asn1Object obj = null;
  207. if(nam) {
  208. obj = _asn1Objects.Where(x => txt == x.OIDString || txt == x.ShortName || txt == x.LongName).FirstOrDefault();
  209. } else {
  210. obj = _asn1Objects.Where(x => txt == x.OIDString).FirstOrDefault();
  211. }
  212. if(obj == null) {
  213. throw PythonOps.ValueError("unknown object '{0}'", txt);
  214. }
  215. return obj.ToTuple();
  216. }
  217. public static object nid2obj(CodeContext context, int nid) {
  218. if(nid < 0) {
  219. throw PythonOps.ValueError("NID must be positive");
  220. }
  221. var obj = _asn1Objects.Where(x => x.NID == nid).FirstOrDefault();
  222. if(obj == null) {
  223. throw PythonOps.ValueError("unknown NID {0}", nid);
  224. }
  225. return obj.ToTuple();
  226. }
  227. public static List enum_certificates(string store_name) {
  228. X509Store store = null;
  229. try {
  230. store = new X509Store(store_name, StoreLocation.LocalMachine);
  231. store.Open(OpenFlags.ReadOnly);
  232. var result = new List();
  233. foreach (var cert in store.Certificates) {
  234. string format = cert.GetFormat();
  235. switch(format) {
  236. case "X509":
  237. format = "x509_asn";
  238. break;
  239. default:
  240. format = "unknown";
  241. break;
  242. }
  243. var set = new SetCollection();
  244. bool found = false;
  245. foreach (var ext in cert.Extensions) {
  246. var keyUsage = ext as X509EnhancedKeyUsageExtension;
  247. if (keyUsage != null) {
  248. foreach(var oid in keyUsage.EnhancedKeyUsages) {
  249. set.add(oid.Value);
  250. }
  251. found = true;
  252. break;
  253. }
  254. }
  255. result.Add(PythonTuple.MakeTuple(new Bytes(cert.RawData.ToList()), format, found ? set : ScriptingRuntimeHelpers.True));
  256. }
  257. return result;
  258. } catch {
  259. } finally {
  260. if(store != null) {
  261. #if NETSTANDARD
  262. store.Dispose();
  263. #else
  264. store.Close();
  265. #endif
  266. }
  267. }
  268. return new List();
  269. }
  270. public static List enum_crls(string store_name) {
  271. X509Store store = null;
  272. try {
  273. store = new X509Store(store_name, StoreLocation.LocalMachine);
  274. store.Open(OpenFlags.ReadOnly);
  275. var result = new List();
  276. foreach (var cert in store.Certificates) {
  277. string format = cert.GetFormat();
  278. }
  279. } catch {
  280. } finally {
  281. if (store != null) {
  282. #if NETSTANDARD
  283. store.Dispose();
  284. #else
  285. store.Close();
  286. #endif
  287. }
  288. }
  289. return new List();
  290. }
  291. internal static PythonType SSLError(CodeContext/*!*/ context) {
  292. return (PythonType)PythonContext.GetContext(context).GetModuleState("SSLError");
  293. }
  294. public static PythonDictionary _test_decode_cert(CodeContext context, string filename, [DefaultParameterValue(false)]bool complete) {
  295. var cert = ReadCertificate(context, filename);
  296. return CertificateToPython(context, cert, complete);
  297. }
  298. internal static PythonDictionary CertificateToPython(CodeContext context, X509Certificate cert, bool complete) {
  299. return CertificateToPython(context, new X509Certificate2(cert.GetRawCertData()), complete);
  300. }
  301. internal static PythonDictionary CertificateToPython(CodeContext context, X509Certificate2 cert, bool complete) {
  302. var dict = new CommonDictionaryStorage();
  303. dict.AddNoLock("notAfter", ToPythonDateFormat(cert.NotAfter.ToString()));
  304. dict.AddNoLock("subject", IssuerToPython(context, cert.Subject));
  305. if (complete) {
  306. dict.AddNoLock("notBefore", ToPythonDateFormat(cert.NotBefore.ToString()));
  307. dict.AddNoLock("serialNumber", SerialNumberToPython(cert));
  308. dict.AddNoLock("version", cert.GetCertHashString());
  309. dict.AddNoLock("issuer", IssuerToPython(context, cert.Issuer));
  310. AddSubjectAltNames(dict, cert);
  311. }
  312. return new PythonDictionary(dict);
  313. }
  314. private static void AddSubjectAltNames(CommonDictionaryStorage dict, X509Certificate2 cert2) {
  315. foreach (var extension in cert2.Extensions) {
  316. if (extension.Oid.Value != "2.5.29.17") { // Subject Alternative Name
  317. continue;
  318. }
  319. var altNames = new List<object>();
  320. var sr = new StringReader(extension.Format(true));
  321. string line;
  322. while (null != (line = sr.ReadLine())) {
  323. line = line.Trim();
  324. var keyValue = line.Split('=');
  325. if (keyValue[0] == "DNS Name" && keyValue.Length == 2) {
  326. altNames.Add(PythonTuple.MakeTuple("DNS", keyValue[1]));
  327. }
  328. }
  329. dict.AddNoLock("subjectAltName", PythonTuple.MakeTuple(altNames.ToArray()));
  330. break;
  331. }
  332. }
  333. private static string ToPythonDateFormat(string date) {
  334. return DateTime.Parse(date).ToUniversalTime().ToString("MMM d HH:mm:ss yyyy") + " GMT";
  335. }
  336. #if NETSTANDARD
  337. private static string ByteArrayToString(IEnumerable<byte> bytes) {
  338. var builder = new StringBuilder();
  339. foreach (byte b in bytes)
  340. builder.Append(b.ToString("X2"));
  341. return builder.ToString();
  342. }
  343. private static string GetSerialNumberString(this X509Certificate cert) {
  344. return ByteArrayToString(cert.GetSerialNumber().Reverse()); // must be reversed
  345. }
  346. private static string GetCertHashString(this X509Certificate cert) {
  347. return ByteArrayToString(cert.GetCertHash());
  348. }
  349. internal static byte[] GetRawCertData(this X509Certificate cert) {
  350. return cert.Export(X509ContentType.Cert);
  351. }
  352. #endif
  353. private static string SerialNumberToPython(X509Certificate cert) {
  354. var res = cert.GetSerialNumberString();
  355. for (int i = 0; i < res.Length; i++) {
  356. if (res[i] != '0') {
  357. return res.Substring(i);
  358. }
  359. }
  360. return res;
  361. }
  362. // yields parts out of issuer or subject string
  363. // Respects quoted comma e.g: CN=*.c.ssl.fastly.net, O="Fastly, Inc.", L=San Francisco, S=California, C=US
  364. // Quote characters are removed
  365. private static IEnumerable<string> IssuerParts(string issuer) {
  366. var inQuote = false;
  367. var token = new StringBuilder();
  368. foreach (var c in issuer) {
  369. if (inQuote) {
  370. if (c == '"') {
  371. inQuote = false;
  372. } else {
  373. token.Append(c);
  374. }
  375. } else {
  376. if (c == '"') {
  377. inQuote = true;
  378. } else if (c == ',') {
  379. yield return token.ToString().Trim();
  380. token.Length = 0;
  381. } else {
  382. token.Append(c);
  383. }
  384. }
  385. }
  386. }
  387. private static PythonTuple IssuerToPython(CodeContext context, string issuer) {
  388. var collector = new List<object>();
  389. foreach (var part in IssuerParts(issuer)) {
  390. var field = IssuerFieldToPython(context, part);
  391. if (field != null) {
  392. collector.Add(field);
  393. }
  394. }
  395. return PythonTuple.MakeTuple(collector.ToArray());
  396. }
  397. private static PythonTuple IssuerFieldToPython(CodeContext context, string p) {
  398. if (String.Compare(p, 0, "CN=", 0, 3) == 0) {
  399. return PythonTuple.MakeTuple("commonName", p.Substring(3));
  400. } else if (String.Compare(p, 0, "OU=", 0, 3) == 0) {
  401. return PythonTuple.MakeTuple("organizationalUnitName", p.Substring(3));
  402. } else if (String.Compare(p, 0, "O=", 0, 2) == 0) {
  403. return PythonTuple.MakeTuple("organizationName", p.Substring(2));
  404. } else if (String.Compare(p, 0, "L=", 0, 2) == 0) {
  405. return PythonTuple.MakeTuple("localityName", p.Substring(2));
  406. } else if (String.Compare(p, 0, "S=", 0, 2) == 0) {
  407. return PythonTuple.MakeTuple("stateOrProvinceName", p.Substring(2));
  408. } else if (String.Compare(p, 0, "C=", 0, 2) == 0) {
  409. return PythonTuple.MakeTuple("countryName", p.Substring(2));
  410. } else if (String.Compare(p, 0, "E=", 0, 2) == 0) {
  411. return PythonTuple.MakeTuple("email", p.Substring(2));
  412. }
  413. // Ignore unknown fields
  414. return null;
  415. }
  416. internal static X509Certificate2 ReadCertificate(CodeContext context, string filename) {
  417. string[] lines;
  418. try {
  419. lines = File.ReadAllLines(filename);
  420. } catch (IOException) {
  421. throw PythonExceptions.CreateThrowable(SSLError(context), "Can't open file ", filename);
  422. }
  423. X509Certificate2 cert = null;
  424. RSACryptoServiceProvider key = null;
  425. try {
  426. for (int i = 0; i < lines.Length; i++) {
  427. if (lines[i] == "-----BEGIN CERTIFICATE-----") {
  428. var certStr = ReadToEnd(lines, ref i, "-----END CERTIFICATE-----");
  429. try {
  430. cert = new X509Certificate2(Convert.FromBase64String(certStr.ToString()));
  431. } catch (Exception e) {
  432. throw ErrorDecoding(context, filename, e);
  433. }
  434. } else if (lines[i] == "-----BEGIN RSA PRIVATE KEY-----") {
  435. var keyStr = ReadToEnd(lines, ref i, "-----END RSA PRIVATE KEY-----");
  436. try {
  437. var keyBytes = Convert.FromBase64String(keyStr.ToString());
  438. key = ParsePkcs1DerEncodedPrivateKey(context, filename, keyBytes);
  439. } catch (Exception e) {
  440. throw ErrorDecoding(context, filename, e);
  441. }
  442. }
  443. }
  444. } catch (InvalidOperationException e) {
  445. throw ErrorDecoding(context, filename, e.Message);
  446. }
  447. if (cert != null) {
  448. #if !NETSTANDARD
  449. if (key != null) {
  450. try {
  451. cert.PrivateKey = key;
  452. } catch(CryptographicException e) {
  453. throw ErrorDecoding(context, filename, "cert and private key are incompatible", e);
  454. }
  455. }
  456. #endif
  457. return cert;
  458. }
  459. throw ErrorDecoding(context, filename, "certificate not found");
  460. }
  461. #region Private Key Parsing
  462. const int ClassOffset = 6;
  463. const int ClassMask = 0xc0;
  464. const int ClassUniversal = 0x00 << ClassOffset;
  465. const int ClassApplication = 0x01 << ClassOffset;
  466. const int ClassContextSpecific = 0x02 << ClassOffset;
  467. const int ClassPrivate = 0x03 << ClassOffset;
  468. const int NumberMask = 0x1f;
  469. const int UnivesalSequence = 0x10;
  470. const int UniversalInteger = 0x02;
  471. const int UniversalOctetString = 0x04;
  472. private static RSACryptoServiceProvider ParsePkcs1DerEncodedPrivateKey(CodeContext context, string filename, byte[] x) {
  473. // http://tools.ietf.org/html/rfc3447#appendix-A.1.2
  474. // RSAPrivateKey ::= SEQUENCE {
  475. // version Version,
  476. // modulus INTEGER, -- n
  477. // publicExponent INTEGER, -- e
  478. // privateExponent INTEGER, -- d
  479. // prime1 INTEGER, -- p
  480. // prime2 INTEGER, -- q
  481. // exponent1 INTEGER, -- d mod (p-1)
  482. // exponent2 INTEGER, -- d mod (q-1)
  483. // coefficient INTEGER, -- (inverse of q) mod p
  484. // otherPrimeInfos OtherPrimeInfos OPTIONAL
  485. // }
  486. // read header for sequence
  487. if ((x[0] & ClassMask) != ClassUniversal) {
  488. throw ErrorDecoding(context, filename, "failed to find universal class");
  489. } else if ((x[0] & NumberMask) != UnivesalSequence) {
  490. throw ErrorDecoding(context, filename, "failed to read sequence header");
  491. }
  492. // read length of sequence
  493. int offset = 1;
  494. ReadLength(x, ref offset);
  495. // read version
  496. int version = ReadUnivesalInt(x, ref offset);
  497. if (version != 0) {
  498. // unsupported version
  499. throw new InvalidOperationException(String.Format("bad vesion: {0}", version));
  500. }
  501. // read in parameters and initialize provider
  502. RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
  503. RSAParameters parameters = new RSAParameters();
  504. parameters.Modulus = ReadUnivesalIntAsBytes(x, ref offset);
  505. parameters.Exponent = ReadUnivesalIntAsBytes(x, ref offset);
  506. parameters.D = ReadUnivesalIntAsBytes(x, ref offset);
  507. parameters.P = ReadUnivesalIntAsBytes(x, ref offset);
  508. parameters.Q = ReadUnivesalIntAsBytes(x, ref offset);
  509. parameters.DP = ReadUnivesalIntAsBytes(x, ref offset);
  510. parameters.DQ = ReadUnivesalIntAsBytes(x, ref offset);
  511. parameters.InverseQ = ReadUnivesalIntAsBytes(x, ref offset);
  512. provider.ImportParameters(parameters);
  513. return provider;
  514. }
  515. private static byte[] ReadUnivesalIntAsBytes(byte[] x, ref int offset) {
  516. ReadIntType(x, ref offset);
  517. int bytes = ReadLength(x, ref offset);
  518. // we need to remove any leading 0 bytes which aren't part of a number. Including
  519. // them causes our parsing to differ from certification parsing.
  520. while (x[offset] == 0) {
  521. bytes--;
  522. offset++;
  523. }
  524. byte[] res = new byte[bytes];
  525. for (int i = 0; i < res.Length; i++) {
  526. res[i] = x[offset++];
  527. }
  528. return res;
  529. }
  530. private static void ReadIntType(byte[] x, ref int offset) {
  531. int versionType = x[offset++];
  532. if (versionType != UniversalInteger) {
  533. throw new InvalidOperationException(String.Format("expected version, fonud {0}", versionType));
  534. }
  535. }
  536. private static int ReadUnivesalInt(byte[] x, ref int offset) {
  537. ReadIntType(x, ref offset);
  538. return ReadInt(x, ref offset);
  539. }
  540. private static int ReadLength(byte[] x, ref int offset) {
  541. int bytes = x[offset++];
  542. if ((bytes & 0x80) == 0) {
  543. return bytes;
  544. }
  545. return ReadInt(x, ref offset, bytes & ~0x80);
  546. }
  547. private static int ReadInt(byte[] x, ref int offset, int bytes) {
  548. if (bytes + offset > x.Length) {
  549. throw new InvalidOperationException();
  550. }
  551. int res = 0;
  552. for (int i = 0; i < bytes; i++) {
  553. res = res << 8 | x[offset++];
  554. }
  555. return res;
  556. }
  557. /// <summary>
  558. /// BER encoding of an integer value is the number of bytes
  559. /// required to represent the integer followed by the bytes
  560. /// </summary>
  561. private static int ReadInt(byte[] x, ref int offset) {
  562. int bytes = x[offset++];
  563. return ReadInt(x, ref offset, bytes);
  564. }
  565. private static string ReadToEnd(string[] lines, ref int start, string end) {
  566. StringBuilder key = new StringBuilder();
  567. for (start++; start < lines.Length; start++) {
  568. if (lines[start] == end) {
  569. return key.ToString();
  570. }
  571. key.Append(lines[start]);
  572. }
  573. return null;
  574. }
  575. #endregion
  576. private static Exception ErrorDecoding(CodeContext context, params object[] args) {
  577. return PythonExceptions.CreateThrowable(SSLError(context), ArrayUtils.Insert("Error decoding PEM-encoded file ", args));
  578. }
  579. #region Exported constants
  580. public const int CERT_NONE = 0;
  581. public const int CERT_OPTIONAL = 1;
  582. public const int CERT_REQUIRED = 2;
  583. public const int PROTOCOL_SSLv2 = 0;
  584. public const int PROTOCOL_SSLv3 = 1;
  585. public const int PROTOCOL_SSLv23 = 2;
  586. public const int PROTOCOL_TLSv1 = 3;
  587. public const int PROTOCOL_TLSv1_1 = 4;
  588. public const int PROTOCOL_TLSv1_2 = 5;
  589. public const uint OP_ALL = 0x80000BFF;
  590. public const uint OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800;
  591. public const int OP_NO_SSLv2 = 0x00000000;
  592. public const int OP_NO_SSLv3 = 0x02000000;
  593. public const int OP_NO_TLSv1 = 0x04000000;
  594. public const int OP_NO_TLSv1_1 = 0x10000000;
  595. public const int OP_NO_TLSv1_2 = 0x08000000;
  596. internal const int OP_NO_ALL = OP_NO_SSLv2 | OP_NO_SSLv3 | OP_NO_TLSv1 | OP_NO_TLSv1_1 | OP_NO_TLSv1_2;
  597. public const int SSL_ERROR_SSL = 1;
  598. public const int SSL_ERROR_WANT_READ = 2;
  599. public const int SSL_ERROR_WANT_WRITE = 3;
  600. public const int SSL_ERROR_WANT_X509_LOOKUP = 4;
  601. public const int SSL_ERROR_SYSCALL = 5;
  602. public const int SSL_ERROR_ZERO_RETURN = 6;
  603. public const int SSL_ERROR_WANT_CONNECT = 7;
  604. public const int SSL_ERROR_EOF = 8;
  605. public const int SSL_ERROR_INVALID_ERROR_CODE = 9;
  606. public const int VERIFY_DEFAULT = 0;
  607. public const int VERIFY_CRL_CHECK_LEAF = 0x4; // from openssl/x509_vfy.h
  608. public const int VERIFY_CRL_CHECK_CHAIN = 0x4 | 0x8; // from openssl/x509_vfy.h
  609. public const int VERIFY_X509_STRICT = 0x20; // from openssl/x509_vfy.h
  610. public const int VERIFY_X509_TRUSTED_FIRST = 0x8000; // from openssl/x509_vfy.h
  611. public const bool HAS_SNI = false;
  612. public const bool HAS_ECDH = true;
  613. public const bool HAS_NPN = false;
  614. public const bool HAS_ALPN = false;
  615. public const bool HAS_TLS_UNIQUE = false;
  616. private const int SSL_VERIFY_NONE = 0x00;
  617. private const int SSL_VERIFY_PEER = 0x01;
  618. private const int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 0x02;
  619. private const int SSL_VERIFY_CLIENT_ONCE = 0x04;
  620. #endregion
  621. }
  622. }
  623. #endif