Annotation of embedaddon/axTLS/bindings/csharp/axTLS.cs, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 2007, Cameron Rich
! 3: *
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions are met:
! 8: *
! 9: * * Redistributions of source code must retain the above copyright notice,
! 10: * this list of conditions and the following disclaimer.
! 11: * * Redistributions in binary form must reproduce the above copyright notice,
! 12: * this list of conditions and the following disclaimer in the documentation
! 13: * and/or other materials provided with the distribution.
! 14: * * Neither the name of the axTLS project nor the names of its contributors
! 15: * may be used to endorse or promote products derived from this software
! 16: * without specific prior written permission.
! 17: *
! 18: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
! 19: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
! 20: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
! 21: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
! 22: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 23: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 24: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
! 25: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
! 26: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
! 27: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
! 28: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 29: */
! 30:
! 31: /**
! 32: * A wrapper around the unmanaged interface to give a semi-decent C# API
! 33: */
! 34:
! 35: using System;
! 36: using System.Runtime.InteropServices;
! 37: using System.Net.Sockets;
! 38:
! 39: /**
! 40: * @defgroup csharp_api C# API.
! 41: *
! 42: * Ensure that the appropriate Dispose() methods are called when finished with
! 43: * various objects - otherwise memory leaks will result.
! 44: * @{
! 45: */
! 46: namespace axTLS
! 47: {
! 48: /**
! 49: * @class SSL
! 50: * @ingroup csharp_api
! 51: * @brief A representation of an SSL connection.
! 52: */
! 53: public class SSL
! 54: {
! 55: public IntPtr m_ssl; /**< A pointer to the real SSL type */
! 56:
! 57: /**
! 58: * @brief Store the reference to an SSL context.
! 59: * @param ip [in] A reference to an SSL object.
! 60: */
! 61: public SSL(IntPtr ip)
! 62: {
! 63: m_ssl = ip;
! 64: }
! 65:
! 66: /**
! 67: * @brief Free any used resources on this connection.
! 68: *
! 69: * A "Close Notify" message is sent on this connection (if possible).
! 70: * It is up to the application to close the socket.
! 71: */
! 72: public void Dispose()
! 73: {
! 74: axtls.ssl_free(m_ssl);
! 75: }
! 76:
! 77: /**
! 78: * @brief Return the result of a handshake.
! 79: * @return SSL_OK if the handshake is complete and ok.
! 80: * @see ssl.h for the error code list.
! 81: */
! 82: public int HandshakeStatus()
! 83: {
! 84: return axtls.ssl_handshake_status(m_ssl);
! 85: }
! 86:
! 87: /**
! 88: * @brief Return the SSL cipher id.
! 89: * @return The cipher id which is one of:
! 90: * - SSL_AES128_SHA (0x2f)
! 91: * - SSL_AES256_SHA (0x35)
! 92: * - SSL_RC4_128_SHA (0x05)
! 93: * - SSL_RC4_128_MD5 (0x04)
! 94: */
! 95: public byte GetCipherId()
! 96: {
! 97: return axtls.ssl_get_cipher_id(m_ssl);
! 98: }
! 99:
! 100: /**
! 101: * @brief Get the session id for a handshake.
! 102: *
! 103: * This will be a 32 byte sequence and is available after the first
! 104: * handshaking messages are sent.
! 105: * @return The session id as a 32 byte sequence.
! 106: * @note A SSLv23 handshake may have only 16 valid bytes.
! 107: */
! 108: public byte[] GetSessionId()
! 109: {
! 110: IntPtr ptr = axtls.ssl_get_session_id(m_ssl);
! 111: byte sess_id_size = axtls.ssl_get_session_id_size(m_ssl);
! 112: byte[] result = new byte[sess_id_size];
! 113: Marshal.Copy(ptr, result, 0, sess_id_size);
! 114: return result;
! 115: }
! 116:
! 117: /**
! 118: * @brief Retrieve an X.509 distinguished name component.
! 119: *
! 120: * When a handshake is complete and a certificate has been exchanged,
! 121: * then the details of the remote certificate can be retrieved.
! 122: *
! 123: * This will usually be used by a client to check that the server's
! 124: * common name matches the URL.
! 125: *
! 126: * A full handshake needs to occur for this call to work.
! 127: *
! 128: * @param component [in] one of:
! 129: * - SSL_X509_CERT_COMMON_NAME
! 130: * - SSL_X509_CERT_ORGANIZATION
! 131: * - SSL_X509_CERT_ORGANIZATIONAL_NAME
! 132: * - SSL_X509_CA_CERT_COMMON_NAME
! 133: * - SSL_X509_CA_CERT_ORGANIZATION
! 134: * - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
! 135: * @return The appropriate string (or null if not defined)
! 136: */
! 137: public string GetCertificateDN(int component)
! 138: {
! 139: return axtls.ssl_get_cert_dn(m_ssl, component);
! 140: }
! 141: }
! 142:
! 143: /**
! 144: * @class SSLUtil
! 145: * @ingroup csharp_api
! 146: * @brief Some global helper functions.
! 147: */
! 148: public class SSLUtil
! 149: {
! 150:
! 151: /**
! 152: * @brief Return the build mode of the axTLS project.
! 153: * @return The build mode is one of:
! 154: * - SSL_BUILD_SERVER_ONLY
! 155: * - SSL_BUILD_ENABLE_VERIFICATION
! 156: * - SSL_BUILD_ENABLE_CLIENT
! 157: * - SSL_BUILD_FULL_MODE
! 158: */
! 159: public static int BuildMode()
! 160: {
! 161: return axtls.ssl_get_config(axtls.SSL_BUILD_MODE);
! 162: }
! 163:
! 164: /**
! 165: * @brief Return the number of chained certificates that the
! 166: * client/server supports.
! 167: * @return The number of supported server certificates.
! 168: */
! 169: public static int MaxCerts()
! 170: {
! 171: return axtls.ssl_get_config(axtls.SSL_MAX_CERT_CFG_OFFSET);
! 172: }
! 173:
! 174: /**
! 175: * @brief Return the number of CA certificates that the client/server
! 176: * supports.
! 177: * @return The number of supported CA certificates.
! 178: */
! 179: public static int MaxCACerts()
! 180: {
! 181: return axtls.ssl_get_config(axtls.SSL_MAX_CA_CERT_CFG_OFFSET);
! 182: }
! 183:
! 184: /**
! 185: * @brief Indicate if PEM is supported.
! 186: * @return true if PEM supported.
! 187: */
! 188: public static bool HasPEM()
! 189: {
! 190: return axtls.ssl_get_config(axtls.SSL_HAS_PEM) > 0 ? true : false;
! 191: }
! 192:
! 193: /**
! 194: * @brief Display the text string of the error.
! 195: * @param error_code [in] The integer error code.
! 196: */
! 197: public static void DisplayError(int error_code)
! 198: {
! 199: axtls.ssl_display_error(error_code);
! 200: }
! 201:
! 202: /**
! 203: * @brief Return the version of the axTLS project.
! 204: */
! 205: public static string Version()
! 206: {
! 207: return axtls.ssl_version();
! 208: }
! 209: }
! 210:
! 211: /**
! 212: * @class SSLCTX
! 213: * @ingroup csharp_api
! 214: * @brief A base object for SSLServer/SSLClient.
! 215: */
! 216: public class SSLCTX
! 217: {
! 218: /**
! 219: * @brief A reference to the real client/server context.
! 220: */
! 221: protected IntPtr m_ctx;
! 222:
! 223: /**
! 224: * @brief Establish a new client/server context.
! 225: *
! 226: * This function is called before any client/server SSL connections are
! 227: * made. If multiple threads are used, then each thread will have its
! 228: * own SSLCTX context. Any number of connections may be made with a
! 229: * single context.
! 230: *
! 231: * Each new connection will use the this context's private key and
! 232: * certificate chain. If a different certificate chain is required,
! 233: * then a different context needs to be be used.
! 234: *
! 235: * @param options [in] Any particular options. At present the options
! 236: * supported are:
! 237: * - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if
! 238: * the server authentication fails. The certificate can be
! 239: * authenticated later with a call to VerifyCert().
! 240: * - SSL_CLIENT_AUTHENTICATION (server only): Enforce client
! 241: * authentication i.e. each handshake will include a "certificate
! 242: * request" message from the server.
! 243: * - SSL_DISPLAY_BYTES (full mode build only): Display the byte
! 244: * sequences during the handshake.
! 245: * - SSL_DISPLAY_STATES (full mode build only): Display the state
! 246: * changes during the handshake.
! 247: * - SSL_DISPLAY_CERTS (full mode build only): Display the
! 248: * certificates that are passed during a handshake.
! 249: * - SSL_DISPLAY_RSA (full mode build only): Display the RSA key
! 250: * details that are passed during a handshake.
! 251: * @param num_sessions [in] The number of sessions to be used for
! 252: * session caching. If this value is 0, then there is no session
! 253: * caching.
! 254: * @return A client/server context.
! 255: */
! 256: protected SSLCTX(uint options, int num_sessions)
! 257: {
! 258: m_ctx = axtls.ssl_ctx_new(options, num_sessions);
! 259: }
! 260:
! 261: /**
! 262: * @brief Remove a client/server context.
! 263: *
! 264: * Frees any used resources used by this context. Each connection will
! 265: * be sent a "Close Notify" alert (if possible).
! 266: */
! 267: public void Dispose()
! 268: {
! 269: axtls.ssl_ctx_free(m_ctx);
! 270: }
! 271:
! 272: /**
! 273: * @brief Read the SSL data stream.
! 274: * @param ssl [in] An SSL object reference.
! 275: * @param in_data [out] After a successful read, the decrypted data
! 276: * will be here. It will be null otherwise.
! 277: * @return The number of decrypted bytes:
! 278: * - if > 0, then the handshaking is complete and we are returning the
! 279: * number of decrypted bytes.
! 280: * - SSL_OK if the handshaking stage is successful (but not yet
! 281: * complete).
! 282: * - < 0 if an error.
! 283: * @see ssl.h for the error code list.
! 284: * @note Use in_data before doing any successive ssl calls.
! 285: */
! 286: public int Read(SSL ssl, out byte[] in_data)
! 287: {
! 288: IntPtr ptr = IntPtr.Zero;
! 289: int ret = axtls.ssl_read(ssl.m_ssl, ref ptr);
! 290:
! 291: if (ret > axtls.SSL_OK)
! 292: {
! 293: in_data = new byte[ret];
! 294: Marshal.Copy(ptr, in_data, 0, ret);
! 295: }
! 296: else
! 297: {
! 298: in_data = null;
! 299: }
! 300:
! 301: return ret;
! 302: }
! 303:
! 304: /**
! 305: * @brief Write to the SSL data stream.
! 306: * @param ssl [in] An SSL obect reference.
! 307: * @param out_data [in] The data to be written
! 308: * @return The number of bytes sent, or if < 0 if an error.
! 309: * @see ssl.h for the error code list.
! 310: */
! 311: public int Write(SSL ssl, byte[] out_data)
! 312: {
! 313: return axtls.ssl_write(ssl.m_ssl, out_data, out_data.Length);
! 314: }
! 315:
! 316: /**
! 317: * @brief Write to the SSL data stream.
! 318: * @param ssl [in] An SSL obect reference.
! 319: * @param out_data [in] The data to be written
! 320: * @param out_len [in] The number of bytes to be written
! 321: * @return The number of bytes sent, or if < 0 if an error.
! 322: * @see ssl.h for the error code list.
! 323: */
! 324: public int Write(SSL ssl, byte[] out_data, int out_len)
! 325: {
! 326: return axtls.ssl_write(ssl.m_ssl, out_data, out_len);
! 327: }
! 328:
! 329: /**
! 330: * @brief Find an ssl object based on a Socket reference.
! 331: *
! 332: * Goes through the list of SSL objects maintained in a client/server
! 333: * context to look for a socket match.
! 334: * @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
! 335: * @return A reference to the SSL object. Returns null if the object
! 336: * could not be found.
! 337: */
! 338: public SSL Find(Socket s)
! 339: {
! 340: int client_fd = s.Handle.ToInt32();
! 341: return new SSL(axtls. ssl_find(m_ctx, client_fd));
! 342: }
! 343:
! 344: /**
! 345: * @brief Authenticate a received certificate.
! 346: *
! 347: * This call is usually made by a client after a handshake is complete
! 348: * and the context is in SSL_SERVER_VERIFY_LATER mode.
! 349: * @param ssl [in] An SSL object reference.
! 350: * @return SSL_OK if the certificate is verified.
! 351: */
! 352: public int VerifyCert(SSL ssl)
! 353: {
! 354: return axtls.ssl_verify_cert(ssl.m_ssl);
! 355: }
! 356:
! 357: /**
! 358: * @brief Force the client to perform its handshake again.
! 359: *
! 360: * For a client this involves sending another "client hello" message.
! 361: * For the server is means sending a "hello request" message.
! 362: *
! 363: * This is a blocking call on the client (until the handshake
! 364: * completes).
! 365: * @param ssl [in] An SSL object reference.
! 366: * @return SSL_OK if renegotiation instantiation was ok
! 367: */
! 368: public int Renegotiate(SSL ssl)
! 369: {
! 370: return axtls.ssl_renegotiate(ssl.m_ssl);
! 371: }
! 372:
! 373: /**
! 374: * @brief Load a file into memory that is in binary DER or ASCII PEM
! 375: * format.
! 376: *
! 377: * These are temporary objects that are used to load private keys,
! 378: * certificates etc into memory.
! 379: * @param obj_type [in] The format of the file. Can be one of:
! 380: * - SSL_OBJ_X509_CERT (no password required)
! 381: * - SSL_OBJ_X509_CACERT (no password required)
! 382: * - SSL_OBJ_RSA_KEY (AES128/AES256 PEM encryption supported)
! 383: * - SSL_OBJ_P8 (RC4-128 encrypted data supported)
! 384: * - SSL_OBJ_P12 (RC4-128 encrypted data supported)
! 385: *
! 386: * PEM files are automatically detected (if supported).
! 387: * @param filename [in] The location of a file in DER/PEM format.
! 388: * @param password [in] The password used. Can be null if not required.
! 389: * @return SSL_OK if all ok
! 390: */
! 391: public int ObjLoad(int obj_type, string filename, string password)
! 392: {
! 393: return axtls.ssl_obj_load(m_ctx, obj_type, filename, password);
! 394: }
! 395:
! 396: /**
! 397: * @brief Transfer binary data into the object loader.
! 398: *
! 399: * These are temporary objects that are used to load private keys,
! 400: * certificates etc into memory.
! 401: * @param obj_type [in] The format of the memory data.
! 402: * @param data [in] The binary data to be loaded.
! 403: * @param len [in] The amount of data to be loaded.
! 404: * @param password [in] The password used. Can be null if not required.
! 405: * @return SSL_OK if all ok
! 406: */
! 407: public int ObjLoad(int obj_type, byte[] data, int len, string password)
! 408: {
! 409: return axtls.ssl_obj_memory_load(m_ctx, obj_type,
! 410: data, len, password);
! 411: }
! 412: }
! 413:
! 414: /**
! 415: * @class SSLServer
! 416: * @ingroup csharp_api
! 417: * @brief The server context.
! 418: *
! 419: * All server connections are started within a server context.
! 420: */
! 421: public class SSLServer : SSLCTX
! 422: {
! 423: /**
! 424: * @brief Start a new server context.
! 425: *
! 426: * @see SSLCTX for details.
! 427: */
! 428: public SSLServer(uint options, int num_sessions) :
! 429: base(options, num_sessions) {}
! 430:
! 431: /**
! 432: * @brief Establish a new SSL connection to an SSL client.
! 433: *
! 434: * It is up to the application to establish the initial socket
! 435: * connection.
! 436: *
! 437: * Call Dispose() when the connection is to be removed.
! 438: * @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
! 439: * @return An SSL object reference.
! 440: */
! 441: public SSL Connect(Socket s)
! 442: {
! 443: int client_fd = s.Handle.ToInt32();
! 444: return new SSL(axtls.ssl_server_new(m_ctx, client_fd));
! 445: }
! 446: }
! 447:
! 448: /**
! 449: * @class SSLClient
! 450: * @ingroup csharp_api
! 451: * @brief The client context.
! 452: *
! 453: * All client connections are started within a client context.
! 454: */
! 455: public class SSLClient : SSLCTX
! 456: {
! 457: /**
! 458: * @brief Start a new client context.
! 459: *
! 460: * @see SSLCTX for details.
! 461: */
! 462: public SSLClient(uint options, int num_sessions) :
! 463: base(options, num_sessions) {}
! 464:
! 465: /**
! 466: * @brief Establish a new SSL connection to an SSL server.
! 467: *
! 468: * It is up to the application to establish the initial socket
! 469: * connection.
! 470: *
! 471: * This is a blocking call - it will finish when the handshake is
! 472: * complete (or has failed).
! 473: *
! 474: * Call Dispose() when the connection is to be removed.
! 475: * @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
! 476: * @param session_id [in] A 32 byte session id for session resumption.
! 477: * This can be null if no session resumption is not required.
! 478: * @return An SSL object reference. Use SSL.handshakeStatus() to check
! 479: * if a handshake succeeded.
! 480: */
! 481: public SSL Connect(Socket s, byte[] session_id)
! 482: {
! 483: int client_fd = s.Handle.ToInt32();
! 484: byte sess_id_size = (byte)(session_id != null ?
! 485: session_id.Length : 0);
! 486: return new SSL(axtls.ssl_client_new(m_ctx, client_fd, session_id,
! 487: sess_id_size));
! 488: }
! 489: }
! 490: }
! 491: /** @} */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>