tls_select.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * TLS module - select interface
00005  *
00006  * Copyright (C) 2001-2003 FhG FOKUS
00007  * Copyright (C) 2004,2005 Free Software Foundation, Inc.
00008  * Copyright (C) 2005 iptelorg GmbH
00009  * Copyright (C) 2006 enum.at
00010  *
00011  * This file is part of sip-router, a free SIP server.
00012  *
00013  * sip-router is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 2 of the License, or
00016  * (at your option) any later version
00017  *
00018  * sip-router is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  */
00034 #include <openssl/ssl.h>
00035 #include <openssl/x509v3.h>
00036 #include "../../globals.h"
00037 #include "../../tcp_server.h"
00038 #include "../../tcp_conn.h"
00039 #include "../../ut.h"
00040 #include "../../cfg/cfg.h"
00041 #include "tls_server.h"
00042 #include "tls_select.h"
00043 #include "tls_mod.h"
00044 #include "tls_init.h" /* features macros */
00045 #include "tls_cfg.h"
00046 
00047 enum {
00048         CERT_LOCAL = 1,   /* Select local certificate */
00049         CERT_PEER,        /* Select peer certificate */
00050         CERT_SUBJECT,     /* Select subject part of certificate */
00051         CERT_ISSUER,      /* Select issuer part of certificate */
00052         CERT_VERIFIED,    /* Test for verified certificate */
00053         CERT_REVOKED,     /* Test for revoked certificate */
00054         CERT_EXPIRED,     /* Expiration certificate test */
00055         CERT_SELFSIGNED,  /* self-signed certificate test */
00056         CERT_NOTBEFORE,   /* Select validity end from certificate */
00057         CERT_NOTAFTER,    /* Select validity start from certificate */
00058         COMP_CN,          /* Common name */
00059         COMP_O,           /* Organization name */
00060         COMP_OU,          /* Organization unit */
00061         COMP_C,           /* Country name */
00062         COMP_ST,          /* State */
00063         COMP_L,           /* Locality/town */
00064         COMP_HOST,        /* hostname from subject/alternative */
00065         COMP_URI,         /* URI from subject/alternative */
00066         COMP_E,           /* Email address */
00067         COMP_IP,          /* IP from subject/alternative */
00068         TLSEXT_SN         /* Server name of the peer */
00069 };
00070 
00071 
00072 enum {
00073         PV_CERT_LOCAL      = 1<<0,   /* Select local certificate */
00074         PV_CERT_PEER       = 1<<1,   /* Select peer certificate */
00075         PV_CERT_SUBJECT    = 1<<2,   /* Select subject part of certificate */
00076         PV_CERT_ISSUER     = 1<<3,   /* Select issuer part of certificate */
00077 
00078         PV_CERT_VERIFIED   = 1<<4,   /* Test for verified certificate */
00079         PV_CERT_REVOKED    = 1<<5,   /* Test for revoked certificate */
00080         PV_CERT_EXPIRED    = 1<<6,   /* Expiration certificate test */
00081         PV_CERT_SELFSIGNED = 1<<7,   /* self-signed certificate test */
00082         PV_CERT_NOTBEFORE  = 1<<8,   /* Select validity end from certificate */
00083         PV_CERT_NOTAFTER   = 1<<9,   /* Select validity start from certificate */
00084 
00085         PV_COMP_CN = 1<<10,          /* Common name */
00086         PV_COMP_O  = 1<<11,          /* Organization name */
00087         PV_COMP_OU = 1<<12,          /* Organization unit */
00088         PV_COMP_C  = 1<<13,          /* Country name */
00089         PV_COMP_ST = 1<<14,          /* State */
00090         PV_COMP_L  = 1<<15,          /* Locality/town */
00091 
00092         PV_COMP_HOST = 1<<16,        /* hostname from subject/alternative */
00093         PV_COMP_URI  = 1<<17,        /* URI from subject/alternative */
00094         PV_COMP_E    = 1<<18,        /* Email address */
00095         PV_COMP_IP   = 1<<19,        /* IP from subject/alternative */
00096 
00097         PV_TLSEXT_SNI = 1<<20,       /* Peer's server name (TLS extension) */
00098 };
00099 
00100 
00101 
00102 
00103 
00104 struct tcp_connection* get_cur_connection(struct sip_msg* msg)
00105 {
00106         struct tcp_connection* c;
00107         if (msg->rcv.proto != PROTO_TLS) {
00108                 ERR("Transport protocol is not TLS (bug in config)\n");
00109                 return 0;
00110         }
00111 
00112         c = tcpconn_get(msg->rcv.proto_reserved1, 0, 0, 0,
00113                                         cfg_get(tls, tls_cfg, con_lifetime));
00114         if (c && c->type != PROTO_TLS) {
00115                 ERR("Connection found but is not TLS\n");
00116                 tcpconn_put(c);
00117                 return 0;
00118         }
00119         return c;
00120 }
00121 
00122 
00123 static SSL* get_ssl(struct tcp_connection* c)
00124 {
00125         struct tls_extra_data* extra;
00126 
00127         if (!c || !c->extra_data) {
00128                 ERR("Unable to extract SSL data from TLS connection\n");
00129                 return 0;
00130         }
00131         extra = (struct tls_extra_data*)c->extra_data;
00132         return extra->ssl;
00133 }
00134 
00135 
00136 static int get_cert(X509** cert, struct tcp_connection** c, struct sip_msg* msg, int my)
00137 {
00138         SSL* ssl;
00139 
00140         *cert = 0;
00141         *c = get_cur_connection(msg);
00142         if (!(*c)) {
00143                 INFO("TLS connection not found\n");
00144                 return -1;
00145         }
00146         ssl = get_ssl(*c);
00147         if (!ssl) goto err;
00148         *cert = my ? SSL_get_certificate(ssl) : SSL_get_peer_certificate(ssl);
00149         if (!*cert) {
00150                 ERR("Unable to retrieve TLS certificate from SSL structure\n");
00151                 goto err;
00152         }
00153         
00154         return 0;
00155         
00156  err:
00157         tcpconn_put(*c);
00158         return -1;
00159 }
00160 
00161 
00162 static int get_cipher(str* res, sip_msg_t* msg) 
00163 {
00164         str cipher;
00165         static char buf[1024];
00166 
00167         struct tcp_connection* c;
00168         SSL* ssl;
00169 
00170         c = get_cur_connection(msg);
00171         if (!c) {
00172                 INFO("TLS connection not found in select_cipher\n");
00173                 goto err;
00174         }
00175         ssl = get_ssl(c);
00176         if (!ssl) goto err;
00177 
00178         cipher.s = (char*)SSL_CIPHER_get_name(SSL_get_current_cipher(ssl));
00179         cipher.len = cipher.s ? strlen(cipher.s) : 0;
00180         if (cipher.len >= 1024) {
00181                 ERR("Cipher name too long\n");
00182                 goto err;
00183         }
00184         memcpy(buf, cipher.s, cipher.len);
00185         res->s = buf;
00186         res->len = cipher.len;
00187         tcpconn_put(c);
00188         return 0;
00189 
00190  err:
00191         if (c) tcpconn_put(c);
00192         return -1;
00193 }
00194 
00195 static int sel_cipher(str* res, select_t* s, sip_msg_t* msg)
00196 {
00197         return get_cipher(res, msg);
00198 }
00199 
00200 
00201 static int pv_cipher(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00202 {
00203         if (get_cipher(&res->rs, msg) < 0) {
00204                 return pv_get_null(msg, param, res);
00205         }
00206         res->flags = PV_VAL_STR;
00207         return 0;
00208 }
00209 
00210 
00211 static int get_bits(str* res, int* i, sip_msg_t* msg) 
00212 {
00213         str bits;
00214         int b;
00215         static char buf[1024];
00216 
00217         struct tcp_connection* c;
00218         SSL* ssl;
00219 
00220         c = get_cur_connection(msg);
00221         if (!c) {
00222                 INFO("TLS connection not found in select_bits\n");
00223                 goto err;
00224         }
00225         ssl = get_ssl(c);
00226         if (!ssl) goto err;
00227 
00228         b = SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), 0);
00229         bits.s = int2str(b, &bits.len);
00230         if (bits.len >= 1024) {
00231                 ERR("Bits string too long\n");
00232                 goto err;
00233         }
00234         memcpy(buf, bits.s, bits.len);
00235         res->s = buf;
00236         res->len = bits.len;
00237         if (i) *i = b;
00238         tcpconn_put(c);
00239         return 0;
00240 
00241  err:
00242         if (c) tcpconn_put(c);
00243         return -1;
00244 }
00245 
00246 
00247 static int sel_bits(str* res, select_t* s, sip_msg_t* msg) 
00248 {
00249         return get_bits(res, NULL, msg);
00250 }
00251 
00252 static int pv_bits(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00253 {
00254         if (get_bits(&res->rs, &res->ri, msg) < 0) {
00255                 return pv_get_null(msg, param, res);
00256         }
00257         res->flags = PV_VAL_STR | PV_VAL_INT;
00258         return 0;
00259 }
00260 
00261 
00262 static int get_version(str* res, sip_msg_t* msg)
00263 {
00264         str version;
00265         static char buf[1024];
00266 
00267         struct tcp_connection* c;
00268         SSL* ssl;
00269 
00270         c = get_cur_connection(msg);
00271         if (!c) {
00272                 INFO("TLS connection not found in select_version\n");
00273                 goto err;
00274         }
00275         ssl = get_ssl(c);
00276         if (!ssl) goto err;
00277 
00278         version.s = (char*)SSL_get_version(ssl);
00279         version.len = version.s ? strlen(version.s) : 0;
00280         if (version.len >= 1024) {
00281                 ERR("Version string too long\n");
00282                 goto err;
00283         }
00284         memcpy(buf, version.s, version.len);
00285         res->s = buf;
00286         res->len = version.len;
00287         tcpconn_put(c);
00288         return 0;
00289 
00290  err:
00291         if (c) tcpconn_put(c);
00292         return -1;
00293 }
00294 
00295 
00296 static int sel_version(str* res, select_t* s, sip_msg_t* msg)
00297 {
00298         return get_version(res, msg);
00299 }
00300 
00301 
00302 static int pv_version(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00303 {
00304         if (get_version(&res->rs, msg) < 0) {
00305                 return pv_get_null(msg, param, res);
00306         }
00307         res->flags = PV_VAL_STR;
00308         return 0;
00309 }
00310 
00311 
00312 
00313 static int get_desc(str* res, sip_msg_t* msg)
00314 {
00315         static char buf[128];
00316 
00317         struct tcp_connection* c;
00318         SSL* ssl;
00319 
00320         c = get_cur_connection(msg);
00321         if (!c) {
00322                 INFO("TLS connection not found in select_desc\n");
00323                 goto err;
00324         }
00325         ssl = get_ssl(c);
00326         if (!ssl) goto err;
00327 
00328         buf[0] = '\0';
00329         SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, 128);
00330         res->s = buf;
00331         res->len = strlen(buf);
00332         tcpconn_put(c);
00333         return 0;
00334 
00335  err:
00336         if (c) tcpconn_put(c);
00337         return -1;      
00338 }
00339 
00340 
00341 static int sel_desc(str* res, select_t* s, sip_msg_t* msg)
00342 {
00343         return get_desc(res, msg);
00344 }
00345 
00346 static int pv_desc(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00347 {
00348         if (get_desc(&res->rs, msg) < 0) {
00349                 return pv_get_null(msg, param, res);
00350         }
00351         res->flags = PV_VAL_STR;
00352         return 0;
00353 }
00354 
00355 
00356 
00357 static int get_cert_version(str* res, int local, sip_msg_t* msg)
00358 {
00359         static char buf[INT2STR_MAX_LEN];
00360         X509* cert;
00361         struct tcp_connection* c;
00362         char* version;
00363 
00364         if (get_cert(&cert, &c, msg, local) < 0) return -1;
00365         version = int2str(X509_get_version(cert), &res->len);
00366         memcpy(buf, version, res->len);
00367         res->s = buf;
00368         if (!local) X509_free(cert);
00369         tcpconn_put(c);
00370         return 0;
00371 }
00372 
00373 static int sel_cert_version(str* res, select_t* s, sip_msg_t* msg)
00374 {
00375         int local;
00376         
00377         switch(s->params[s->n - 2].v.i) {
00378         case CERT_PEER: local = 0; break;
00379         case CERT_LOCAL: local = 1; break;
00380         default:
00381                 BUG("Bug in call to sel_cert_version\n");
00382                 return -1;
00383         }
00384 
00385         return get_cert_version(res, local, msg);
00386 }
00387 
00388 static int pv_cert_version(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00389 {
00390         int local;
00391         
00392         if (param->pvn.u.isname.name.n & PV_CERT_PEER) {
00393                 local = 0;
00394         } else if (param->pvn.u.isname.name.n & PV_CERT_LOCAL) {
00395                 local = 1;
00396         } else {
00397                 BUG("bug in call to pv_cert_version\n");
00398                 return pv_get_null(msg, param, res);
00399         }
00400 
00401         if (get_cert_version(&res->rs, local, msg) < 0) {
00402                 return pv_get_null(msg, param, res);
00403         }
00404         res->flags = PV_VAL_STR;
00405         return 0;
00406 }
00407 
00408 
00409 
00410 /*
00411  * Check whether peer certificate exists and verify the result
00412  * of certificate verification
00413  */
00414 static int check_cert(str* res, int* ires, int local, int err, sip_msg_t* msg)
00415 {
00416         static str succ = STR_STATIC_INIT("1");
00417         static str fail = STR_STATIC_INIT("0");
00418 
00419         struct tcp_connection* c;
00420         SSL* ssl;
00421         X509* cert = 0;
00422 
00423         c = get_cur_connection(msg);
00424         if (!c) return -1;
00425 
00426         ssl = get_ssl(c);
00427         if (!ssl) goto error;
00428 
00429         if (local) {
00430                 DBG("Verification of local certificates not supported\n");
00431                 goto error;
00432         } else {
00433                 if ((cert = SSL_get_peer_certificate(ssl)) && SSL_get_verify_result(ssl) == err) {
00434                         *res = succ;
00435                         if (ires) *ires = 1;
00436                 } else {
00437                         *res = fail;
00438                         if (ires) *ires = 0;
00439                 }
00440         }
00441 
00442         if (cert) X509_free(cert);
00443         tcpconn_put(c);
00444         return 0;
00445 
00446  error:
00447         if (cert) X509_free(cert);
00448         if (c) tcpconn_put(c);
00449         return -1;
00450 }
00451 
00452 
00453 static int sel_check_cert(str* res, select_t* s, sip_msg_t* msg)
00454 {
00455         int local, err;
00456         
00457         switch(s->params[s->n - 2].v.i) {
00458         case CERT_PEER: local = 0; break;
00459         case CERT_LOCAL: local = 1; break;
00460         default:
00461                 BUG("Bug in call to sel_cert_version\n");
00462                 return -1;
00463         }
00464 
00465         switch (s->params[s->n - 1].v.i) {
00466         case CERT_VERIFIED:   err = X509_V_OK;                              break;
00467         case CERT_REVOKED:    err = X509_V_ERR_CERT_REVOKED;                break;
00468         case CERT_EXPIRED:    err = X509_V_ERR_CERT_HAS_EXPIRED;            break;
00469         case CERT_SELFSIGNED: err = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; break;
00470         default:
00471                 BUG("Unexpected parameter value \"%d\"\n", s->params[s->n - 1].v.i);
00472                 return -1;
00473         }   
00474 
00475         return check_cert(res, NULL, local, err, msg);
00476 }
00477 
00478 static int pv_check_cert(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00479 {
00480         int err;
00481         
00482         switch (param->pvn.u.isname.name.n) {
00483         case PV_CERT_VERIFIED:   err = X509_V_OK;                              break;
00484         case PV_CERT_REVOKED:    err = X509_V_ERR_CERT_REVOKED;                break;
00485         case PV_CERT_EXPIRED:    err = X509_V_ERR_CERT_HAS_EXPIRED;            break;
00486         case PV_CERT_SELFSIGNED: err = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; break;
00487         default:
00488                 BUG("unexpected parameter value \"%d\"\n", param->pvn.u.isname.name.n);
00489                 return pv_get_null(msg, param, res);
00490         }
00491         
00492 
00493         if (check_cert(&res->rs, &res->ri, 0, err, msg) < 0) {
00494                 return pv_get_null(msg, param, res);
00495         }
00496 
00497         res->flags = PV_VAL_STR | PV_VAL_INT;
00498         return 0;
00499 }
00500 
00501 
00502 
00503 
00504 static int get_validity(str* res, int local, int bound, sip_msg_t* msg)
00505 {
00506 #define NOT_BEFORE 0
00507 #define NOT_AFTER 1
00508         static char buf[1024];
00509         X509* cert;
00510         struct tcp_connection* c;
00511         BUF_MEM* p;
00512         BIO* mem = 0;
00513         ASN1_TIME* date;
00514 
00515         if (get_cert(&cert, &c, msg, local) < 0) return -1;
00516 
00517         switch (bound) {
00518         case NOT_BEFORE: date = X509_get_notBefore(cert); break;
00519         case NOT_AFTER:  date = X509_get_notAfter(cert);  break;
00520         default:
00521                 BUG("Unexpected parameter value \"%d\"\n", bound);
00522                 goto err;
00523         }
00524 
00525         mem = BIO_new(BIO_s_mem());
00526         if (!mem) {
00527                 ERR("Error while creating memory BIO\n");
00528                 goto err;
00529         }
00530 
00531         if (!ASN1_TIME_print(mem, date)) {
00532                 ERR("Error while printing certificate date/time\n");
00533                 goto err;
00534         }
00535         
00536         BIO_get_mem_ptr(mem, &p);
00537         if (p->length >= 1024) {
00538                 ERR("Date/time too long\n");
00539                 goto err;
00540         }
00541         memcpy(buf, p->data, p->length);
00542         res->s = buf;
00543         res->len = p->length;
00544 
00545         BIO_free(mem);
00546         if (!local) X509_free(cert);
00547         tcpconn_put(c);
00548         return 0;
00549  err:
00550         if (mem) BIO_free(mem);
00551         if (!local) X509_free(cert);
00552         tcpconn_put(c);
00553         return -1;
00554 }
00555 
00556 static int sel_validity(str* res, select_t* s, sip_msg_t* msg)
00557 {
00558         int local, bound;
00559         
00560         switch(s->params[s->n - 2].v.i) {
00561         case CERT_PEER:  local = 0; break;
00562         case CERT_LOCAL: local = 1; break;
00563         default:
00564                 BUG("Could not determine certificate\n");
00565                 return -1;
00566         }
00567 
00568         switch (s->params[s->n - 1].v.i) {
00569         case CERT_NOTBEFORE: bound = NOT_BEFORE; break;
00570         case CERT_NOTAFTER:  bound = NOT_AFTER; break;
00571         default:
00572                 BUG("Unexpected parameter value \"%d\"\n", s->params[s->n - 1].v.i);
00573                 return -1;
00574         }
00575 
00576         return get_validity(res, local, bound, msg);
00577 }
00578 
00579 
00580 static int pv_validity(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00581 {
00582         int bound;
00583         
00584         switch (param->pvn.u.isname.name.n) {
00585         case PV_CERT_NOTBEFORE: bound = NOT_BEFORE; break;
00586         case PV_CERT_NOTAFTER:  bound = NOT_AFTER;  break;
00587         default:
00588                 BUG("unexpected parameter value \"%d\"\n", param->pvn.u.isname.name.n);
00589                 return pv_get_null(msg, param, res);
00590         }
00591 
00592         if (get_validity(&res->rs, 0, bound, msg) < 0) {
00593                 return pv_get_null(msg, param, res);
00594         }
00595         
00596         res->flags = PV_VAL_STR;
00597         return 0;
00598 }
00599 
00600 
00601 static int get_sn(str* res, int* ires, int local, sip_msg_t* msg)
00602 {
00603         static char buf[INT2STR_MAX_LEN];
00604         X509* cert;
00605         struct tcp_connection* c;
00606         char* sn;
00607         int num;
00608 
00609         if (get_cert(&cert, &c, msg, local) < 0) return -1;
00610 
00611         num = ASN1_INTEGER_get(X509_get_serialNumber(cert));
00612         sn = int2str(num, &res->len);
00613         memcpy(buf, sn, res->len);
00614         res->s = buf;
00615         if (ires) *ires = num;
00616         if (!local) X509_free(cert);
00617         tcpconn_put(c);
00618         return 0;
00619 }
00620 
00621 static int sel_sn(str* res, select_t* s, sip_msg_t* msg)
00622 {
00623         int local;
00624 
00625         switch(s->params[s->n - 2].v.i) {
00626         case CERT_PEER:  local = 0; break;
00627         case CERT_LOCAL: local = 1; break;
00628         default:
00629                 BUG("Could not determine certificate\n");
00630                 return -1;
00631         }
00632 
00633         return get_sn(res, NULL, local, msg);
00634 }
00635 
00636 
00637 static int pv_sn(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00638 {
00639         int local;
00640         
00641         if (param->pvn.u.isname.name.n & PV_CERT_PEER) {
00642                 local = 0;
00643         } else if (param->pvn.u.isname.name.n & PV_CERT_LOCAL) {
00644                 local = 1;
00645         } else {
00646                 BUG("could not determine certificate\n");
00647                 return pv_get_null(msg, param, res);
00648         }
00649         
00650         if (get_sn(&res->rs, &res->ri, local, msg) < 0) {
00651                 return pv_get_null(msg, param, res);
00652         }
00653         
00654         res->flags = PV_VAL_STR | PV_VAL_INT;
00655         return 0;
00656 }
00657 
00658 
00659 
00660 static int get_comp(str* res, int local, int issuer, int nid, sip_msg_t* msg)
00661 {
00662         static char buf[1024];
00663         X509* cert;
00664         struct tcp_connection* c;
00665         X509_NAME* name;
00666         X509_NAME_ENTRY* e;
00667         ASN1_STRING* asn1;
00668         int index, text_len;
00669         char* elem;
00670         unsigned char* text_s;
00671                
00672         text_s = 0;
00673 
00674         if (get_cert(&cert, &c, msg, local) < 0) return -1;
00675 
00676         name = issuer ? X509_get_issuer_name(cert) : X509_get_subject_name(cert);
00677         if (!name) {
00678                 ERR("Cannot extract subject or issuer name from peer certificate\n");
00679                 goto err;
00680         }
00681 
00682         index = X509_NAME_get_index_by_NID(name, nid, -1);
00683         if (index == -1) {
00684                 switch(nid) {
00685                 case NID_commonName:             elem = "CommonName";              break;
00686                 case NID_organizationName:       elem = "OrganizationName";        break;
00687                 case NID_organizationalUnitName: elem = "OrganizationalUnitUname"; break;
00688                 case NID_countryName:            elem = "CountryName";             break;
00689                 case NID_stateOrProvinceName:    elem = "StateOrProvinceName";     break;
00690                 case NID_localityName:           elem = "LocalityName";            break;
00691                 default:                         elem = "Unknown";                 break;
00692                 }
00693                 DBG("Element %s not found in certificate subject/issuer\n", elem);
00694                 goto err;
00695         }
00696 
00697         e = X509_NAME_get_entry(name, index);
00698         asn1 = X509_NAME_ENTRY_get_data(e);
00699         text_len = ASN1_STRING_to_UTF8(&text_s, asn1);
00700         if (text_len < 0 || text_len >= 1024) {
00701                 ERR("Error converting ASN1 string\n");
00702                 goto err;
00703         }
00704         memcpy(buf, text_s, text_len);
00705         res->s = buf;
00706         res->len = text_len;
00707 
00708         OPENSSL_free(text_s);
00709         if (!local) X509_free(cert);
00710         tcpconn_put(c);
00711         return 0;
00712 
00713  err:
00714         if (text_s) OPENSSL_free(text_s);
00715         if (!local) X509_free(cert);
00716         tcpconn_put(c);
00717         return -1;
00718 }
00719 
00720 
00721 static int sel_comp(str* res, select_t* s, sip_msg_t* msg)
00722 {
00723         int i, local = 0, issuer = 0;
00724         int nid = NID_commonName;
00725 
00726         for(i = 1; i <= s->n - 1; i++) {
00727                 switch(s->params[i].v.i) {
00728                 case CERT_LOCAL:   local = 1;                        break;
00729                 case CERT_PEER:    local = 0;                        break;
00730                 case CERT_SUBJECT: issuer = 0;                       break;
00731                 case CERT_ISSUER:  issuer = 1;                       break;
00732                 case COMP_CN:      nid = NID_commonName;             break;
00733                 case COMP_O:       nid = NID_organizationName;       break;
00734                 case COMP_OU:      nid = NID_organizationalUnitName; break;
00735                 case COMP_C:       nid = NID_countryName;            break;
00736                 case COMP_ST:      nid = NID_stateOrProvinceName;    break;
00737                 case COMP_L:       nid = NID_localityName;           break;
00738                 default:
00739                         BUG("Bug in sel_comp: %d\n", s->params[s->n - 1].v.i);
00740                         return -1;
00741                 }
00742         }
00743 
00744         return get_comp(res, local, issuer, nid, msg);
00745 }
00746 
00747 
00748 static int pv_comp(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00749 {
00750         int ind_local, local = 0, issuer = 0, nid = NID_commonName;
00751 
00752         /* copy callback value as we modify it */
00753         ind_local = param->pvn.u.isname.name.n; 
00754         DBG("ind_local = %x", ind_local);
00755 
00756         if (ind_local & PV_CERT_PEER) {
00757                 local = 0;
00758                 ind_local = ind_local ^ PV_CERT_PEER;
00759         } else if (ind_local & PV_CERT_LOCAL) {
00760                 local = 1;
00761                 ind_local = ind_local ^ PV_CERT_LOCAL;
00762         } else {
00763                 BUG("could not determine certificate\n");
00764                 return pv_get_null(msg, param, res);
00765         }
00766 
00767         if (ind_local & PV_CERT_SUBJECT) {
00768                 issuer = 0;
00769                 ind_local = ind_local ^ PV_CERT_SUBJECT;
00770         } else if (ind_local & PV_CERT_ISSUER) {
00771                 issuer = 1;
00772                 ind_local = ind_local ^ PV_CERT_ISSUER;
00773         } else {
00774                 BUG("could not determine subject or issuer\n");
00775                 return pv_get_null(msg, param, res);
00776         }
00777 
00778         switch(ind_local) {
00779                 case PV_COMP_CN: nid = NID_commonName;             break;
00780                 case PV_COMP_O:  nid = NID_organizationName;       break;
00781                 case PV_COMP_OU: nid = NID_organizationalUnitName; break;
00782                 case PV_COMP_C:  nid = NID_countryName;            break;
00783                 case PV_COMP_ST: nid = NID_stateOrProvinceName;    break;
00784                 case PV_COMP_L:  nid = NID_localityName;           break;
00785                 default:      nid = NID_undef;
00786         }
00787 
00788         if (get_comp(&res->rs, local, issuer, nid, msg) < 0) {
00789                 return pv_get_null(msg, param, res);
00790         }
00791 
00792         res->flags = PV_VAL_STR;
00793         return 0;
00794 }
00795 
00796 
00797 static int get_alt(str* res, int local, int type, sip_msg_t* msg)
00798 {
00799         static char buf[1024];
00800         int n, found = 0;
00801         STACK_OF(GENERAL_NAME)* names = 0;
00802         GENERAL_NAME* nm;
00803         X509* cert;
00804         struct tcp_connection* c;
00805         str text;
00806         struct ip_addr ip;
00807 
00808         if (get_cert(&cert, &c, msg, local) < 0) return -1;
00809 
00810         names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
00811         if (!names) {
00812                 DBG("Cannot get certificate alternative subject\n");
00813                 goto err;
00814 
00815         }
00816 
00817         for (n = 0; n < sk_GENERAL_NAME_num(names); n++) {
00818                 nm = sk_GENERAL_NAME_value(names, n);
00819                 if (nm->type != type) continue;
00820                 switch(type) {
00821                 case GEN_EMAIL:
00822                 case GEN_DNS:
00823                 case GEN_URI:
00824                         text.s = (char*)nm->d.ia5->data;
00825                         text.len = nm->d.ia5->length;
00826                         if (text.len >= 1024) {
00827                                 ERR("Alternative subject text too long\n");
00828                                 goto err;
00829                         }
00830                         memcpy(buf, text.s, text.len);
00831                         res->s = buf;
00832                         res->len = text.len;
00833                         found = 1;
00834                         break;
00835 
00836                 case GEN_IPADD:
00837                         ip.len = nm->d.iPAddress->length;
00838                         ip.af = (ip.len == 16) ? AF_INET6 : AF_INET;
00839                         memcpy(ip.u.addr, nm->d.iPAddress->data, ip.len);
00840                         text.s = ip_addr2a(&ip);
00841                         text.len = strlen(text.s);
00842                         memcpy(buf, text.s, text.len);
00843                         res->s = buf;
00844                         res->len = text.len;
00845                         found = 1;
00846                         break;
00847                 }
00848                 break;
00849         }
00850         if (!found) goto err;
00851 
00852         if (names) sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
00853         if (!local) X509_free(cert);
00854         tcpconn_put(c);
00855         return 0;
00856  err:
00857         if (names) sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
00858         if (!local) X509_free(cert);
00859         tcpconn_put(c);
00860         return -1;
00861 }
00862 
00863 static int sel_alt(str* res, select_t* s, sip_msg_t* msg)
00864 {
00865         int type = GEN_URI, local = 0, i;
00866 
00867         for(i = 1; i <= s->n - 1; i++) {
00868                 switch(s->params[i].v.i) {
00869                 case CERT_LOCAL: local = 1; break;
00870                 case CERT_PEER:  local = 0; break;
00871                 case COMP_E:     type = GEN_EMAIL; break;
00872                 case COMP_HOST:  type = GEN_DNS;   break;
00873                 case COMP_URI:   type = GEN_URI;   break;
00874                 case COMP_IP:    type = GEN_IPADD; break;
00875                 default:
00876                         BUG("Bug in sel_alt: %d\n", s->params[s->n - 1].v.i);
00877                         return -1;
00878                 }
00879         }
00880         
00881         return get_alt(res, local, type, msg);
00882 }
00883 
00884 
00885 static int pv_alt(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
00886 {
00887         int ind_local, local = 0, type = GEN_URI;
00888         
00889         ind_local = param->pvn.u.isname.name.n;
00890 
00891         if (ind_local & PV_CERT_PEER) {
00892                 local = 0;
00893                 ind_local = ind_local ^ PV_CERT_PEER;
00894         } else if (ind_local & PV_CERT_LOCAL) {
00895                 local = 1;
00896                 ind_local = ind_local ^ PV_CERT_LOCAL;
00897         } else {
00898                 BUG("could not determine certificate\n");
00899                 return pv_get_null(msg, param, res);
00900         }
00901 
00902         switch(ind_local) {
00903                 case PV_COMP_E:    type = GEN_EMAIL; break;
00904                 case PV_COMP_HOST: type = GEN_DNS;   break;
00905                 case PV_COMP_URI:  type = GEN_URI;   break;
00906                 case PV_COMP_IP:   type = GEN_IPADD; break;
00907                 default:
00908                         BUG("ind_local=%d\n", ind_local);
00909                         return pv_get_null(msg, param, res);
00910         }
00911 
00912         if (get_alt(&res->rs, local, type, msg) < 0) {
00913                 return pv_get_null(msg, param, res);
00914         }
00915         
00916         res->flags = PV_VAL_STR;
00917         return 0;
00918 }
00919 
00920 
00921 static int sel_tls(str* res, select_t* s, struct sip_msg* msg)
00922 {
00923         return sel_desc(res, s, msg);
00924 }
00925 
00926 
00927 static int sel_name(str* res, select_t* s, struct sip_msg* msg)
00928 {
00929         return sel_comp(res, s, msg);
00930 }
00931 
00932 
00933 static int sel_cert(str* res, select_t* s, struct sip_msg* msg)
00934 {
00935         return sel_comp(res, s, msg);
00936 }
00937 
00938 
00939 #ifdef OPENSSL_NO_TLSEXT
00940 static int get_tlsext_sn(str* res, sip_msg_t* msg)
00941 {
00942         ERR("TLS extension 'server name' is not available! "
00943                 "please install openssl with TLS extension support and recompile "
00944                 "the server\n");
00945         return -1;
00946 }
00947 #else
00948 static int get_tlsext_sn(str* res, sip_msg_t* msg)
00949 {
00950         static char buf[1024];
00951         struct tcp_connection* c;
00952         str server_name;        
00953         SSL* ssl;
00954 
00955         c = get_cur_connection(msg);
00956         if (!c) {
00957                 INFO("TLS connection not found in select_desc\n");
00958                 goto error;
00959         }
00960         ssl = get_ssl(c);
00961         if (!ssl) goto error;
00962 
00963         buf[0] = '\0';
00964 
00965         server_name.s = (char*)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
00966         if (server_name.s) {
00967                 server_name.len = strlen(server_name.s);
00968                 DBG("received server_name (TLS extension): '%.*s'\n", 
00969                         STR_FMT(&server_name));
00970         } else {
00971                 DBG("SSL_get_servername returned NULL\n");
00972                 goto error;
00973         }
00974         
00975         /* copy server_name into the buffer. If the buffer is too small copy only
00976          * the last bytes as these are the more important ones and prefix with
00977          * '+' */
00978         if (server_name.len > sizeof(buf)) {
00979                 ERR("server_name to big for buffer\n");
00980                 buf[0] = '+';
00981                 memcpy(buf + 1, server_name.s + 1 + server_name.len - sizeof(buf), 
00982                            sizeof(buf) - 1);
00983                 res->len = sizeof(buf);
00984         } else {
00985                 memcpy(buf, server_name.s, server_name.len);
00986                 res->len = server_name.len;
00987         }
00988         res->s = buf;
00989         
00990         tcpconn_put(c);
00991         return 0;
00992         
00993 error:
00994         if (c) tcpconn_put(c);
00995         return -1;
00996 }
00997 #endif
00998 
00999 
01000 static int sel_tlsext_sn(str* res, select_t* s, sip_msg_t* msg)
01001 {
01002         return get_tlsext_sn(res, msg);
01003 }
01004 
01005 
01006 static int pv_tlsext_sn(sip_msg_t* msg, pv_param_t* param, pv_value_t* res)
01007 {
01008         if (param->pvn.u.isname.name.n != PV_TLSEXT_SNI) {
01009                 BUG("unexpected parameter value \"%d\"\n",
01010                         param->pvn.u.isname.name.n);
01011                 return pv_get_null(msg, param, res);
01012         }
01013         
01014         if (get_tlsext_sn(&res->rs, msg) < 0) {
01015                 return pv_get_null(msg, param, res);
01016         }
01017         
01018         res->flags = PV_VAL_STR;
01019         return 0;
01020 }
01021 
01022 
01023 
01024 
01025 
01026 select_row_t tls_sel[] = {
01027         /* Current cipher parameters */
01028         { NULL, SEL_PARAM_STR, STR_STATIC_INIT("tls"), sel_tls, 0},
01029         
01030         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("version"),     sel_version, 0},
01031         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("desc"),        sel_desc,    0},
01032         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("description"), sel_desc,    0},
01033         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("cipher"),      sel_cipher,  0},
01034 
01035         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("serverName"), sel_tlsext_sn,  0},
01036         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("server_name"), sel_tlsext_sn,  0},
01037 
01038         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("peer"),        sel_cert,    DIVERSION | CERT_PEER},
01039         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("my"),          sel_cert,    DIVERSION | CERT_LOCAL},
01040         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("me"),          sel_cert,    DIVERSION | CERT_LOCAL},
01041         { sel_tls, SEL_PARAM_STR, STR_STATIC_INIT("myself"),      sel_cert,    DIVERSION | CERT_LOCAL},
01042         
01043         { sel_cipher, SEL_PARAM_STR, STR_STATIC_INIT("bits"), sel_bits, 0},
01044         
01045         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("subject"), sel_name, DIVERSION | CERT_SUBJECT},
01046         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("subj"),    sel_name, DIVERSION | CERT_SUBJECT},
01047         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("issuer"),  sel_name, DIVERSION | CERT_ISSUER},
01048 
01049         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("verified"),    sel_check_cert, DIVERSION | CERT_VERIFIED},
01050         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("revoked"),     sel_check_cert, DIVERSION | CERT_REVOKED},
01051         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("expired"),     sel_check_cert, DIVERSION | CERT_EXPIRED},
01052         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("self_signed"), sel_check_cert, DIVERSION | CERT_SELFSIGNED},
01053 
01054         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("version"), sel_cert_version, 0},
01055 
01056         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("sn"),            sel_sn, 0},
01057         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("serialNumber"),  sel_sn, 0},
01058         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("serial_number"), sel_sn, 0},
01059 
01060         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("notBefore"),  sel_validity, DIVERSION | CERT_NOTBEFORE},
01061         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("not_before"), sel_validity, DIVERSION | CERT_NOTBEFORE},
01062         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("notAfter"),   sel_validity, DIVERSION | CERT_NOTAFTER},
01063         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("not_after"),  sel_validity, DIVERSION | CERT_NOTAFTER},
01064 
01065         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("email"),         sel_alt, DIVERSION | COMP_E},
01066         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("emailAddress"),  sel_alt, DIVERSION | COMP_E},
01067         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("email_address"), sel_alt, DIVERSION | COMP_E},
01068 
01069         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("host"),     sel_alt, DIVERSION | COMP_HOST},
01070         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("hostname"), sel_alt, DIVERSION | COMP_HOST},
01071         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("dns"),      sel_alt, DIVERSION | COMP_HOST},
01072 
01073         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("uri"), sel_alt, DIVERSION | COMP_URI},
01074         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("url"), sel_alt, DIVERSION | COMP_URI},
01075         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("urn"), sel_alt, DIVERSION | COMP_URI},
01076 
01077         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("ip"),         sel_alt, DIVERSION | COMP_IP},
01078         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("IPAddress"),  sel_alt, DIVERSION | COMP_IP},
01079         { sel_cert, SEL_PARAM_STR, STR_STATIC_INIT("ip_address"), sel_alt, DIVERSION | COMP_IP},
01080 
01081         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("cn"),          sel_comp, DIVERSION | COMP_CN},
01082         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("commonName"),  sel_comp, DIVERSION | COMP_CN},
01083         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("common_name"), sel_comp, DIVERSION | COMP_CN},
01084         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("name"),        sel_comp, DIVERSION | COMP_CN},
01085 
01086         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("l"),             sel_comp, DIVERSION | COMP_L},
01087         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("localityName"),  sel_comp, DIVERSION | COMP_L},
01088         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("locality_name"), sel_comp, DIVERSION | COMP_L},
01089         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("locality"),      sel_comp, DIVERSION | COMP_L},
01090 
01091         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("c"),            sel_comp, DIVERSION | COMP_C},
01092         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("countryName"),  sel_comp, DIVERSION | COMP_C},
01093         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("country_name"), sel_comp, DIVERSION | COMP_C},
01094         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("country"),      sel_comp, DIVERSION | COMP_C},
01095 
01096         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("st"),                     sel_comp, DIVERSION | COMP_ST},
01097         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("stateOrProvinceName"),    sel_comp, DIVERSION | COMP_ST},
01098         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("state_or_province_name"), sel_comp, DIVERSION | COMP_ST},
01099         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("state"),                  sel_comp, DIVERSION | COMP_ST},
01100 
01101         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("o"),                 sel_comp, DIVERSION | COMP_O},
01102         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("organizationName"),  sel_comp, DIVERSION | COMP_O},
01103         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("organization_name"), sel_comp, DIVERSION | COMP_O},
01104         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("organization"),      sel_comp, DIVERSION | COMP_O},
01105 
01106         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("ou"),                       sel_comp, DIVERSION | COMP_OU},
01107         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("organizationalUnitName"),   sel_comp, DIVERSION | COMP_OU},
01108         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("organizational_unit_name"), sel_comp, DIVERSION | COMP_OU},
01109         { sel_name, SEL_PARAM_STR, STR_STATIC_INIT("unit"),                     sel_comp, DIVERSION | COMP_OU},
01110 
01111         { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
01112 };
01113 
01114 
01115 /*
01116  *  pseudo variables
01117  */
01118 pv_export_t tls_pv[] = {
01119         /* TLS session parameters */
01120         {{"tls_version", sizeof("tls_version")-1},
01121                 PVT_OTHER, pv_version, 0,
01122                 0, 0, 0, 0 },
01123         {{"tls_description", sizeof("tls_description")-1},
01124                 PVT_OTHER, pv_desc, 0,
01125                 0, 0, 0, 0 },
01126         {{"tls_cipher_info", sizeof("tls_cipher_info")-1},
01127                 PVT_OTHER, pv_cipher, 0,
01128                 0, 0, 0, 0 },
01129         {{"tls_cipher_bits", sizeof("tls_cipher_bits")-1},
01130                 PVT_OTHER,  pv_bits, 0,
01131                 0, 0, 0, 0 },
01132         /* general certificate parameters for peer and local */
01133         {{"tls_peer_version", sizeof("tls_peer_version")-1},
01134                 PVT_OTHER, pv_cert_version, 0,
01135                 0, 0, pv_init_iname, PV_CERT_PEER  },
01136         {{"tls_my_version", sizeof("tls_my_version")-1},
01137                 PVT_OTHER, pv_cert_version, 0,
01138                 0, 0, pv_init_iname, PV_CERT_LOCAL },
01139         {{"tls_peer_serial", sizeof("tls_peer_serial")-1},
01140                 PVT_OTHER, pv_sn, 0,
01141                 0, 0, pv_init_iname, PV_CERT_PEER  },
01142         {{"tls_my_serial", sizeof("tls_my_serial")-1},
01143                 PVT_OTHER, pv_sn,0,
01144                 0, 0, pv_init_iname, PV_CERT_LOCAL },
01145         /* certificate parameters for peer and local, for subject and issuer*/  
01146         {{"tls_peer_subject", sizeof("tls_peer_subject")-1},
01147                 PVT_OTHER, pv_comp, 0,
01148                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_SUBJECT },
01149         {{"tls_peer_issuer", sizeof("tls_peer_issuer")-1},
01150                 PVT_OTHER, pv_comp, 0,
01151                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_ISSUER  },
01152         {{"tls_my_subject", sizeof("tls_my_subject")-1},
01153                 PVT_OTHER, pv_comp, 0,
01154                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_SUBJECT },
01155         {{"tls_my_issuer", sizeof("tls_my_issuer")-1},
01156                 PVT_OTHER, pv_comp, 0,
01157                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_ISSUER  },
01158         {{"tls_peer_subject_cn", sizeof("tls_peer_subject_cn")-1},
01159                 PVT_OTHER, pv_comp, 0,
01160                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_SUBJECT | PV_COMP_CN },
01161         {{"tls_peer_issuer_cn", sizeof("tls_peer_issuer_cn")-1},
01162                 PVT_OTHER, pv_comp, 0,
01163                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_ISSUER  | PV_COMP_CN },
01164         {{"tls_my_subject_cn", sizeof("tls_my_subject_cn")-1},
01165                 PVT_OTHER, pv_comp, 0,
01166                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_SUBJECT | PV_COMP_CN },
01167         {{"tls_my_issuer_cn", sizeof("tls_my_issuer_cn")-1},
01168                 PVT_OTHER, pv_comp, 0,
01169                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_ISSUER  | PV_COMP_CN },
01170         {{"tls_peer_subject_locality", sizeof("tls_peer_subject_locality")-1},
01171                 PVT_OTHER, pv_comp, 0,
01172                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_SUBJECT | PV_COMP_L },
01173         {{"tls_peer_issuer_locality", sizeof("tls_peer_issuer_locality")-1},
01174                 PVT_OTHER, pv_comp, 0,
01175                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_ISSUER  | PV_COMP_L },
01176         {{"tls_my_subject_locality", sizeof("tls_my_subject_locality")-1},
01177                 PVT_OTHER, pv_comp, 0,
01178                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_SUBJECT | PV_COMP_L },
01179         {{"tls_my_issuer_locality", sizeof("tls_my_issuer_locality")-1},
01180                 PVT_OTHER, pv_comp, 0,
01181                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_ISSUER  | PV_COMP_L },
01182         {{"tls_peer_subject_country", sizeof("tls_peer_subject_country")-1},
01183                 PVT_OTHER, pv_comp, 0,
01184                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_SUBJECT | PV_COMP_C },
01185         {{"tls_peer_issuer_country", sizeof("tls_peer_issuer_country")-1},
01186                 PVT_OTHER, pv_comp, 0,
01187                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_ISSUER  | PV_COMP_C },
01188         {{"tls_my_subject_country", sizeof("tls_my_subject_country")-1},
01189                 PVT_OTHER, pv_comp, 0,
01190                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_SUBJECT | PV_COMP_C },
01191         {{"tls_my_issuer_country", sizeof("tls_my_issuer_country")-1},
01192                 PVT_OTHER, pv_comp, 0,
01193                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_ISSUER  | PV_COMP_C },
01194         {{"tls_peer_subject_state", sizeof("tls_peer_subject_state")-1},
01195                 PVT_OTHER, pv_comp, 0,
01196                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_SUBJECT | PV_COMP_ST },
01197         {{"tls_peer_issuer_state", sizeof("tls_peer_issuer_state")-1},
01198                 PVT_OTHER, pv_comp, 0,
01199                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_ISSUER  | PV_COMP_ST },
01200         {{"tls_my_subject_state", sizeof("tls_my_subject_state")-1},
01201                 PVT_OTHER, pv_comp, 0,
01202                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_SUBJECT | PV_COMP_ST },
01203         {{"tls_my_issuer_state", sizeof("tls_my_issuer_state")-1},
01204                 PVT_OTHER, pv_comp, 0,
01205                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_ISSUER  | PV_COMP_ST },
01206         {{"tls_peer_subject_organization", sizeof("tls_peer_subject_organization")-1},
01207                 PVT_OTHER, pv_comp, 0,
01208                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_SUBJECT | PV_COMP_O },
01209         {{"tls_peer_issuer_organization", sizeof("tls_peer_issuer_organization")-1},
01210                 PVT_OTHER, pv_comp, 0,
01211                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_ISSUER  | PV_COMP_O },
01212         {{"tls_my_subject_organization", sizeof("tls_my_subject_organization")-1},
01213                 PVT_OTHER, pv_comp, 0,
01214                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_SUBJECT | PV_COMP_O },
01215         {{"tls_my_issuer_organization", sizeof("tls_my_issuer_organization")-1},
01216                 PVT_OTHER, pv_comp, 0,
01217                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_ISSUER  | PV_COMP_O },
01218         {{"tls_peer_subject_unit", sizeof("tls_peer_subject_unit")-1},
01219                 PVT_OTHER, pv_comp, 0,
01220                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_SUBJECT | PV_COMP_OU },
01221         {{"tls_peer_issuer_unit", sizeof("tls_peer_issuer_unit")-1},
01222                 PVT_OTHER, pv_comp, 0,
01223                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_CERT_ISSUER  | PV_COMP_OU },
01224         {{"tls_my_subject_unit", sizeof("tls_my_subject_unit")-1},
01225                 PVT_OTHER, pv_comp, 0,
01226                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_SUBJECT | PV_COMP_OU },
01227         {{"tls_my_issuer_unit", sizeof("tls_my_issuer_unit")-1},
01228                 PVT_OTHER, pv_comp, 0,
01229                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_CERT_ISSUER  | PV_COMP_OU },
01230         /* subject alternative name parameters for peer and local */    
01231         {{"tls_peer_san_email", sizeof("tls_peer_san_email")-1},
01232                 PVT_OTHER, pv_alt, 0,
01233                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_COMP_E },
01234         {{"tls_my_san_email", sizeof("tls_my_san_email")-1},
01235                 PVT_OTHER, pv_alt, 0,
01236                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_COMP_E },
01237         {{"tls_peer_san_hostname", sizeof("tls_peer_san_hostname")-1},
01238                 PVT_OTHER, pv_alt, 0,
01239                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_COMP_HOST },
01240         {{"tls_my_san_hostname", sizeof("tls_my_san_hostname")-1},
01241                 PVT_OTHER, pv_alt, 0,
01242                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_COMP_HOST },
01243         {{"tls_peer_san_uri", sizeof("tls_peer_san_uri")-1},
01244                 PVT_OTHER, pv_alt, 0,
01245                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_COMP_URI },
01246         {{"tls_my_san_uri", sizeof("tls_my_san_uri")-1},
01247                 PVT_OTHER, pv_alt, 0,
01248                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_COMP_URI },
01249         {{"tls_peer_san_ip", sizeof("tls_peer_san_ip")-1},
01250                 PVT_OTHER, pv_alt, 0,
01251                 0, 0, pv_init_iname, PV_CERT_PEER  | PV_COMP_IP },
01252         {{"tls_my_san_ip", sizeof("tls_my_san_ip")-1},
01253                 PVT_OTHER, pv_alt, 0,
01254                 0, 0, pv_init_iname, PV_CERT_LOCAL | PV_COMP_IP },
01255         /* peer certificate validation parameters */            
01256         {{"tls_peer_verified", sizeof("tls_peer_verified")-1},
01257                 PVT_OTHER, pv_check_cert, 0,
01258                 0, 0, pv_init_iname, PV_CERT_VERIFIED },
01259         {{"tls_peer_revoked", sizeof("tls_peer_revoked")-1},
01260                 PVT_OTHER, pv_check_cert, 0,
01261                 0, 0, pv_init_iname, PV_CERT_REVOKED },
01262         {{"tls_peer_expired", sizeof("tls_peer_expired")-1},
01263                 PVT_OTHER, pv_check_cert, 0,
01264                 0, 0, pv_init_iname, PV_CERT_EXPIRED },
01265         {{"tls_peer_selfsigned", sizeof("tls_peer_selfsigned")-1},
01266                 PVT_OTHER, pv_check_cert, 0,
01267                 0, 0, pv_init_iname, PV_CERT_SELFSIGNED },
01268         {{"tls_peer_notBefore", sizeof("tls_peer_notBefore")-1},
01269                 PVT_OTHER, pv_validity, 0,
01270                 0, 0, pv_init_iname, PV_CERT_NOTBEFORE },
01271         {{"tls_peer_notAfter", sizeof("tls_peer_notAfter")-1},
01272                 PVT_OTHER, pv_validity, 0,
01273                 0, 0, pv_init_iname, PV_CERT_NOTAFTER },
01274         /* peer certificate validation parameters */            
01275         {{"tls_peer_server_name", sizeof("tls_peer_server_name")-1},
01276                 PVT_OTHER, pv_tlsext_sn, 0,
01277                 0, 0, pv_init_iname, PV_TLSEXT_SNI },
01278 
01279         { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
01280 
01281 };