Changeset 5472 for pjproject


Ignore:
Timestamp:
Oct 27, 2016 7:58:01 AM (7 years ago)
Author:
ming
Message:

Fixed #1975: Add support to select elliptic curve and signature algorithm for TLS

Location:
pjproject/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/include/pj/config.h

    r5445 r5472  
    888888#ifndef PJ_SSL_SOCK_OSSL_CIPHERS 
    889889#  define PJ_SSL_SOCK_OSSL_CIPHERS   "HIGH:-COMPLEMENTOFDEFAULT" 
     890#endif 
     891 
     892 
     893/** 
     894 * Define the maximum number of curves supported by the secure socket. 
     895 * 
     896 * Default: 32 
     897 */ 
     898#ifndef PJ_SSL_SOCK_MAX_CURVES 
     899#  define PJ_SSL_SOCK_MAX_CURVES   32 
    890900#endif 
    891901 
  • pjproject/trunk/pjlib/include/pj/ssl_sock.h

    r5238 r5472  
    402402PJ_DECL(pj_ssl_cipher) pj_ssl_cipher_id(const char *cipher_name); 
    403403 
     404/** 
     405 * Elliptic curves enumeration. 
     406 */ 
     407typedef enum pj_ssl_curve 
     408{ 
     409        PJ_TLS_UNKNOWN_CURVE            = 0, 
     410        PJ_TLS_CURVE_SECT163K1          = 1, 
     411        PJ_TLS_CURVE_SECT163R1          = 2, 
     412        PJ_TLS_CURVE_SECT163R2          = 3, 
     413        PJ_TLS_CURVE_SECT193R1          = 4, 
     414        PJ_TLS_CURVE_SECT193R2          = 5, 
     415        PJ_TLS_CURVE_SECT233K1          = 6, 
     416        PJ_TLS_CURVE_SECT233R1          = 7, 
     417        PJ_TLS_CURVE_SECT239K1          = 8, 
     418        PJ_TLS_CURVE_SECT283K1          = 9, 
     419        PJ_TLS_CURVE_SECT283R1          = 10, 
     420        PJ_TLS_CURVE_SECT409K1          = 11, 
     421        PJ_TLS_CURVE_SECT409R1          = 12, 
     422        PJ_TLS_CURVE_SECT571K1          = 13, 
     423        PJ_TLS_CURVE_SECT571R1          = 14, 
     424        PJ_TLS_CURVE_SECP160K1          = 15, 
     425        PJ_TLS_CURVE_SECP160R1          = 16, 
     426        PJ_TLS_CURVE_SECP160R2          = 17, 
     427        PJ_TLS_CURVE_SECP192K1          = 18, 
     428        PJ_TLS_CURVE_SECP192R1          = 19, 
     429        PJ_TLS_CURVE_SECP224K1          = 20, 
     430        PJ_TLS_CURVE_SECP224R1          = 21, 
     431        PJ_TLS_CURVE_SECP256K1          = 22, 
     432        PJ_TLS_CURVE_SECP256R1          = 23, 
     433        PJ_TLS_CURVE_SECP384R1          = 24, 
     434        PJ_TLS_CURVE_SECP521R1          = 25, 
     435        PJ_TLS_CURVE_BRAINPOOLP256R1    = 26, 
     436        PJ_TLS_CURVE_BRAINPOOLP384R1    = 27, 
     437        PJ_TLS_CURVE_BRAINPOOLP512R1    = 28, 
     438        PJ_TLS_CURVE_ARBITRARY_EXPLICIT_PRIME_CURVES    = 0XFF01, 
     439        PJ_TLS_CURVE_ARBITRARY_EXPLICIT_CHAR2_CURVES    = 0XFF02 
     440} pj_ssl_curve; 
     441 
     442/** 
     443 * Get curve list supported by SSL/TLS backend. 
     444 * 
     445 * @param curves        The curves buffer to receive curve list. 
     446 * @param curves_num    Maximum number of curves to be received. 
     447 * 
     448 * @return              PJ_SUCCESS when successful. 
     449 */ 
     450PJ_DECL(pj_status_t) pj_ssl_curve_get_availables(pj_ssl_curve curves[], 
     451                                                 unsigned *curve_num); 
     452 
     453/** 
     454 * Check if the specified curve is supported by SSL/TLS backend. 
     455 * 
     456 * @param curve         The curve. 
     457 * 
     458 * @return              PJ_TRUE when supported. 
     459 */ 
     460PJ_DECL(pj_bool_t) pj_ssl_curve_is_supported(pj_ssl_curve curve); 
     461 
     462 
     463/** 
     464 * Get curve name string. 
     465 * 
     466 * @param curve         The curve. 
     467 * 
     468 * @return              The curve name or NULL if curve is not recognized/ 
     469 *                      supported. 
     470 */ 
     471PJ_DECL(const char*) pj_ssl_curve_name(pj_ssl_curve curve); 
     472 
     473/** 
     474 * Get curve ID from curve name string. Note that on different backends 
     475 * (e.g. OpenSSL or Symbian implementation), curve names may not be 
     476 * equivalent for the same curve ID. 
     477 * 
     478 * @param curve_name    The curve name string. 
     479 * 
     480 * @return              The curve ID or PJ_TLS_UNKNOWN_CURVE if the curve 
     481 *                      name string is not recognized/supported. 
     482 */ 
     483PJ_DECL(pj_ssl_curve) pj_ssl_curve_id(const char *curve_name); 
     484 
     485/* 
     486 * Entropy enumeration 
     487 */ 
     488typedef enum pj_ssl_entropy 
     489{ 
     490        PJ_SSL_ENTROPY_NONE     = 0, 
     491        PJ_SSL_ENTROPY_EGD      = 1, 
     492        PJ_SSL_ENTROPY_RANDOM   = 2, 
     493        PJ_SSL_ENTROPY_URANDOM  = 3, 
     494        PJ_SSL_ENTROPY_FILE     = 4, 
     495        PJ_SSL_ENTROPY_UNKNOWN  = 0x0F 
     496} pj_ssl_entropy_t; 
    404497 
    405498/** 
     
    771864 
    772865    /** 
     866     * Number of curves contained in the specified curve preference. 
     867     * If this is set to zero, then default curve list of the backend 
     868     * will be used. 
     869     * 
     870     * Default: 0 (zero). 
     871     */ 
     872    unsigned curves_num; 
     873 
     874    /** 
     875     * Curves and order preference. The #pj_ssl_curve_get_availables() 
     876     * can be used to check the available curves supported by backend. 
     877     */ 
     878    pj_ssl_curve *curves; 
     879 
     880    /** 
     881     * The supported signature algorithms. Set the sigalgs string 
     882     * using this form: 
     883     * "<DIGEST>+<ALGORITHM>:<DIGEST>+<ALGORITHM>" 
     884     * Digests are: "RSA", "DSA" or "ECDSA" 
     885     * Algorithms are: "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512" 
     886     * Example: "ECDSA+SHA256:RSA+SHA256" 
     887     */ 
     888    pj_str_t    sigalgs; 
     889 
     890    /** 
     891     * Reseed random number generator. 
     892     * For type #PJ_SSL_ENTROPY_FILE, parameter \a entropy_path 
     893     * must be set to a file. 
     894     * For type #PJ_SSL_ENTROPY_EGD, parameter \a entropy_path 
     895     * must be set to a socket. 
     896     * 
     897     * Default value is PJ_SSL_ENTROPY_NONE. 
     898    */ 
     899    pj_ssl_entropy_t    entropy_type; 
     900 
     901    /** 
     902     * When using a file/socket for entropy #PJ_SSL_ENTROPY_EGD or 
     903     * #PJ_SSL_ENTROPY_FILE, \a entropy_path must contain the path 
     904     * to entropy socket/file. 
     905     * 
     906     * Default value is an empty string. 
     907     */ 
     908    pj_str_t            entropy_path; 
     909 
     910    /** 
    773911     * Security negotiation timeout. If this is set to zero (both sec and  
    774912     * msec), the negotiation doesn't have a timeout. 
  • pjproject/trunk/pjlib/src/pj/ssl_sock_common.c

    r5214 r5472  
    6868    } 
    6969 
     70    if (src->curves_num > 0) { 
     71        unsigned i; 
     72        dst->curves = (pj_ssl_curve *)pj_pool_calloc(pool, src->curves_num, 
     73                                                     sizeof(pj_ssl_curve)); 
     74        for (i = 0; i < src->curves_num; ++i) 
     75            dst->curves[i] = src->curves[i]; 
     76    } 
     77 
    7078    if (src->server_name.slen) { 
    7179        /* Server name must be null-terminated */ 
    7280        pj_strdup_with_null(pool, &dst->server_name, &src->server_name); 
     81    } 
     82 
     83    if (src->sigalgs.slen) { 
     84        /* Sigalgs name must be null-terminated */ 
     85        pj_strdup_with_null(pool, &dst->sigalgs, &src->sigalgs); 
     86    } 
     87 
     88    if (src->entropy_path.slen) { 
     89        /* Path name must be null-terminated */ 
     90        pj_strdup_with_null(pool, &dst->entropy_path, &src->entropy_path); 
    7391    } 
    7492} 
  • pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c

    r5459 r5472  
    5050#include <openssl/err.h> 
    5151#include <openssl/x509v3.h> 
    52  
     52#include <openssl/rand.h> 
     53#include <openssl/engine.h> 
     54 
     55#if !defined(OPENSSL_NO_EC) 
     56   extern int tls1_ec_nid2curve_id(int nid); 
     57   extern int tls1_ec_curve_id2nid(int curve_id); 
     58#endif 
    5359 
    5460#ifdef _MSC_VER 
     
    300306} openssl_ciphers[PJ_SSL_SOCK_MAX_CIPHERS]; 
    301307 
     308/* OpenSSL available curves */ 
     309static unsigned openssl_curves_num; 
     310static struct openssl_curves_t { 
     311    pj_ssl_curve    id; 
     312    const char      *name; 
     313} openssl_curves[PJ_SSL_SOCK_MAX_CURVES]; 
     314 
    302315/* OpenSSL application data index */ 
    303316static int sslsock_idx; 
     
    329342 
    330343    /* Init available ciphers */ 
    331     if (openssl_cipher_num == 0) { 
     344    if (openssl_cipher_num == 0 || openssl_curves_num == 0) { 
    332345        SSL_METHOD *meth = NULL; 
    333346        SSL_CTX *ctx; 
     
    335348        STACK_OF(SSL_CIPHER) *sk_cipher; 
    336349        unsigned i, n; 
     350        int nid; 
     351        const char *cname; 
    337352 
    338353        meth = (SSL_METHOD*)SSLv23_server_method(); 
     
    353368 
    354369        ssl = SSL_new(ctx); 
     370 
    355371        sk_cipher = SSL_get_ciphers(ssl); 
    356372 
     
    366382            openssl_ciphers[i].name = SSL_CIPHER_get_name(c); 
    367383        } 
     384        openssl_cipher_num = n; 
     385 
     386        ssl->session = SSL_SESSION_new(); 
     387 
     388#if !defined(OPENSSL_NO_EC) 
     389        openssl_curves_num = SSL_get_shared_curve(ssl,-1); 
     390        if (openssl_curves_num > PJ_ARRAY_SIZE(openssl_curves)) 
     391            openssl_curves_num = PJ_ARRAY_SIZE(openssl_curves); 
     392 
     393        for (i = 0; i < openssl_curves_num; i++) { 
     394            nid = SSL_get_shared_curve(ssl, i); 
     395 
     396            if (nid & TLSEXT_nid_unknown) { 
     397                cname = "curve unknown"; 
     398                nid &= 0xFFFF; 
     399            } else { 
     400                cname = EC_curve_nid2nist(nid); 
     401                if (!cname) 
     402                    cname = OBJ_nid2sn(nid); 
     403            } 
     404 
     405            openssl_curves[i].id   = tls1_ec_nid2curve_id(nid); 
     406            openssl_curves[i].name = cname; 
     407        } 
     408#else 
     409        openssl_curves_num = 0; 
     410#endif 
    368411 
    369412        SSL_free(ssl); 
    370413        SSL_CTX_free(ctx); 
    371  
    372         openssl_cipher_num = n; 
    373414    } 
    374415 
     
    376417    sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL); 
    377418 
    378     return PJ_SUCCESS; 
     419    return status; 
    379420} 
    380421 
     
    499540/* Setting SSL sock cipher list */ 
    500541static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock); 
    501  
     542/* Setting SSL sock curves list */ 
     543static pj_status_t set_curves_list(pj_ssl_sock_t *ssock); 
     544/* Setting sigalgs list */ 
     545static pj_status_t set_sigalgs(pj_ssl_sock_t *ssock); 
     546/* Setting entropy for rng */ 
     547static void set_entropy(pj_ssl_sock_t *ssock); 
    502548 
    503549/* Create and initialize new SSL context and instance */ 
     
    523569    /* Make sure OpenSSL library has been initialized */ 
    524570    init_openssl(); 
     571 
     572    set_entropy(ssock); 
    525573 
    526574    if (ssock->param.proto == PJ_SSL_SOCK_PROTO_DEFAULT) 
     
    776824        return status; 
    777825 
     826    /* Set curve list */ 
     827    status = set_curves_list(ssock); 
     828    if (status != PJ_SUCCESS) 
     829        return status; 
     830 
     831    /* Set sigalg list */ 
     832    status = set_sigalgs(ssock); 
     833    if (status != PJ_SUCCESS) 
     834        return status; 
     835 
    778836    /* Setup SSL BIOs */ 
    779837    ssock->ossl_rbio = BIO_new(BIO_s_mem()); 
     
    940998} 
    941999 
     1000static pj_status_t set_curves_list(pj_ssl_sock_t *ssock) 
     1001{ 
     1002#if !defined(OPENSSL_NO_EC) 
     1003    int ret; 
     1004    int curves[PJ_SSL_SOCK_MAX_CURVES]; 
     1005    int cnt; 
     1006 
     1007    if (ssock->param.curves_num == 0) 
     1008        return PJ_SUCCESS; 
     1009 
     1010    for (cnt = 0; cnt < ssock->param.curves_num; cnt++) { 
     1011        curves[cnt] = tls1_ec_curve_id2nid(ssock->param.curves[cnt]); 
     1012    } 
     1013 
     1014    if( ssock->ossl_ssl->server ) { 
     1015        ret = SSL_set1_curves(ssock->ossl_ssl, curves, 
     1016                              ssock->param.curves_num); 
     1017        if (ret < 1) 
     1018            return GET_SSL_STATUS(ssock); 
     1019    } else { 
     1020        ret = SSL_CTX_set1_curves(ssock->ossl_ctx, curves, 
     1021                                  ssock->param.curves_num); 
     1022        if (ret < 1) 
     1023            return GET_SSL_STATUS(ssock); 
     1024    } 
     1025 
     1026    return PJ_SUCCESS; 
     1027#else 
     1028    return PJ_ENOTSUP; 
     1029#endif 
     1030} 
     1031 
     1032static pj_status_t set_sigalgs(pj_ssl_sock_t *ssock) 
     1033{ 
     1034    int ret; 
     1035 
     1036    if (ssock->param.sigalgs.ptr && ssock->param.sigalgs.slen) { 
     1037        if (ssock->is_server) { 
     1038            ret = SSL_set1_client_sigalgs_list(ssock->ossl_ssl, 
     1039                                               ssock->param.sigalgs.ptr); 
     1040        } else { 
     1041            ret = SSL_set1_sigalgs_list(ssock->ossl_ssl, 
     1042                                        ssock->param.sigalgs.ptr); 
     1043        } 
     1044 
     1045        if (ret < 1) 
     1046            return GET_SSL_STATUS(ssock); 
     1047    } 
     1048 
     1049    return PJ_SUCCESS; 
     1050} 
     1051 
     1052static void set_entropy(pj_ssl_sock_t *ssock) 
     1053{ 
     1054    int ret; 
     1055 
     1056    switch (ssock->param.entropy_type) { 
     1057#ifndef OPENSSL_NO_EGD 
     1058        case PJ_SSL_ENTROPY_EGD: 
     1059            ret = RAND_egd(ssock->param.entropy_path.ptr); 
     1060            break; 
     1061#endif 
     1062        case PJ_SSL_ENTROPY_RANDOM: 
     1063            ret = RAND_load_file("/dev/random",255); 
     1064            break; 
     1065        case PJ_SSL_ENTROPY_URANDOM: 
     1066            ret = RAND_load_file("/dev/urandom",255); 
     1067            break; 
     1068        case PJ_SSL_ENTROPY_FILE: 
     1069            ret = RAND_load_file(ssock->param.entropy_path.ptr,255); 
     1070            break; 
     1071        case PJ_SSL_ENTROPY_NONE: 
     1072            default: 
     1073            return; 
     1074            break; 
     1075    } 
     1076 
     1077    if (ret < 0) { 
     1078        PJ_LOG(3, (ssock->pool->obj_name, "SSL failed to reseed with " 
     1079                                          "entropy type %d", 
     1080                                          ssock->param.entropy_type)); 
     1081    } 
     1082} 
    9421083 
    9431084/* Parse OpenSSL ASN1_TIME to pj_time_val and GMT info */ 
     
    22322373} 
    22332374 
     2375/* Get available curves. */ 
     2376PJ_DEF(pj_status_t) pj_ssl_curve_get_availables(pj_ssl_curve curves[], 
     2377                                                unsigned *curve_num) 
     2378{ 
     2379    unsigned i; 
     2380 
     2381    PJ_ASSERT_RETURN(curves && curve_num, PJ_EINVAL); 
     2382 
     2383    if (openssl_curves_num == 0) { 
     2384        init_openssl(); 
     2385        shutdown_openssl(); 
     2386    } 
     2387 
     2388    if (openssl_curves_num == 0) { 
     2389        *curve_num = 0; 
     2390        return PJ_ENOTFOUND; 
     2391    } 
     2392 
     2393    *curve_num = PJ_MIN(*curve_num, openssl_curves_num); 
     2394 
     2395    for (i = 0; i < *curve_num; ++i) 
     2396    curves[i] = openssl_curves[i].id; 
     2397 
     2398    return PJ_SUCCESS; 
     2399} 
     2400 
     2401/* Get curve name string. */ 
     2402PJ_DEF(const char*) pj_ssl_curve_name(pj_ssl_curve curve) 
     2403{ 
     2404    unsigned i; 
     2405 
     2406    if (openssl_curves_num == 0) { 
     2407        init_openssl(); 
     2408        shutdown_openssl(); 
     2409    } 
     2410 
     2411    for (i = 0; i < openssl_curves_num; ++i) { 
     2412        if (curve == openssl_curves[i].id) 
     2413            return openssl_curves[i].name; 
     2414    } 
     2415 
     2416    return NULL; 
     2417} 
     2418 
     2419/* Get curve ID from curve name string. */ 
     2420PJ_DEF(pj_ssl_curve) pj_ssl_curve_id(const char *curve_name) 
     2421{ 
     2422    unsigned i; 
     2423 
     2424    if (openssl_curves_num == 0) { 
     2425        init_openssl(); 
     2426        shutdown_openssl(); 
     2427    } 
     2428 
     2429    for (i = 0; i < openssl_curves_num; ++i) { 
     2430        if (!pj_ansi_stricmp(openssl_curves[i].name, curve_name)) 
     2431            return openssl_curves[i].id; 
     2432    } 
     2433 
     2434    return PJ_TLS_UNKNOWN_CURVE; 
     2435} 
     2436 
     2437/* Check if the specified curve is supported by SSL/TLS backend. */ 
     2438PJ_DEF(pj_bool_t) pj_ssl_curve_is_supported(pj_ssl_curve curve) 
     2439{ 
     2440    unsigned i; 
     2441 
     2442    if (openssl_curves_num == 0) { 
     2443        init_openssl(); 
     2444        shutdown_openssl(); 
     2445    } 
     2446 
     2447    for (i = 0; i < openssl_curves_num; ++i) { 
     2448        if (curve == openssl_curves[i].id) 
     2449            return PJ_TRUE; 
     2450    } 
     2451 
     2452    return PJ_FALSE; 
     2453} 
    22342454 
    22352455/* 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h

    r5089 r5472  
    142142 
    143143    /** 
     144     * Number of curves contained in the specified curve preference. 
     145     * If this is set to zero, then default curve list of the backend 
     146     * will be used. 
     147     * 
     148     * Default: 0 (zero). 
     149     */ 
     150    unsigned curves_num; 
     151 
     152    /** 
     153     * Curves and order preference. The #pj_ssl_curve_get_availables() 
     154     * can be used to check the available curves supported by backend. 
     155     */ 
     156    pj_ssl_curve *curves; 
     157 
     158    /** 
     159     * The supported signature algorithms. Set the sigalgs string 
     160     * using this form: 
     161     * "<DIGEST>+<ALGORITHM>:<DIGEST>+<ALGORITHM>" 
     162     * Digests are: "RSA", "DSA" or "ECDSA" 
     163     * Algorithms are: "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512" 
     164     * Example: "ECDSA+SHA256:RSA+SHA256" 
     165     */ 
     166    pj_str_t    sigalgs; 
     167 
     168    /** 
     169     * Reseed random number generator. 
     170     * For type #PJ_SSL_ENTROPY_FILE, parameter \a entropy_path 
     171     * must be set to a file. 
     172     * For type #PJ_SSL_ENTROPY_EGD, parameter \a entropy_path 
     173     * must be set to a socket. 
     174     * 
     175     * Default value is PJ_SSL_ENTROPY_NONE. 
     176    */ 
     177    pj_ssl_entropy_t    entropy_type; 
     178 
     179    /** 
     180     * When using a file/socket for entropy #PJ_SSL_ENTROPY_EGD or 
     181     * #PJ_SSL_ENTROPY_FILE, \a entropy_path must contain the path 
     182     * to entropy socket/file. 
     183     * 
     184     * Default value is an empty string. 
     185     */ 
     186    pj_str_t            entropy_path; 
     187 
     188    /** 
    144189     * Specifies TLS transport behavior on the server TLS certificate  
    145190     * verification result: 
     
    293338    pj_strdup_with_null(pool, &dst->privkey_file, &src->privkey_file); 
    294339    pj_strdup_with_null(pool, &dst->password, &src->password); 
     340    pj_strdup_with_null(pool, &dst->sigalgs, &src->sigalgs); 
     341    pj_strdup_with_null(pool, &dst->entropy_path, &src->entropy_path); 
    295342    if (src->ciphers_num) { 
    296343        unsigned i; 
     
    299346        for (i=0; i<src->ciphers_num; ++i) 
    300347            dst->ciphers[i] = src->ciphers[i]; 
     348    } 
     349 
     350    if (src->curves_num) { 
     351        unsigned i; 
     352        dst->curves = (pj_ssl_curve*) pj_pool_calloc(pool, src->curves_num, 
     353                                                     sizeof(pj_ssl_curve)); 
     354        for (i=0; i<src->curves_num; ++i) 
     355            dst->curves[i] = src->curves[i]; 
    301356    } 
    302357} 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c

    r5386 r5472  
    392392    ssock_param.ciphers_num = listener->tls_setting.ciphers_num; 
    393393    ssock_param.ciphers = listener->tls_setting.ciphers; 
     394    ssock_param.curves_num = listener->tls_setting.curves_num; 
     395    ssock_param.curves = listener->tls_setting.curves; 
     396    ssock_param.sigalgs = listener->tls_setting.sigalgs; 
     397    ssock_param.entropy_type = listener->tls_setting.entropy_type; 
     398    ssock_param.entropy_path = listener->tls_setting.entropy_path; 
    394399    ssock_param.reuse_addr = listener->tls_setting.reuse_addr; 
    395400    ssock_param.qos_type = listener->tls_setting.qos_type; 
     
    10711076    ssock_param.ciphers_num = listener->tls_setting.ciphers_num; 
    10721077    ssock_param.ciphers = listener->tls_setting.ciphers; 
     1078    ssock_param.curves_num = listener->tls_setting.curves_num; 
     1079    ssock_param.curves = listener->tls_setting.curves; 
     1080    ssock_param.sigalgs = listener->tls_setting.sigalgs; 
     1081    ssock_param.entropy_type = listener->tls_setting.entropy_type; 
     1082    ssock_param.entropy_path = listener->tls_setting.entropy_path; 
    10731083    ssock_param.qos_type = listener->tls_setting.qos_type; 
    10741084    ssock_param.qos_ignore_error = listener->tls_setting.qos_ignore_error; 
Note: See TracChangeset for help on using the changeset viewer.