Back to index

courier  0.68.2
libcouriertls.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2000-2009 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 #include      "config.h"
00006 #include      "argparse.h"
00007 #include      "spipe.h"
00008 #define COURIERTCPD_EXPOSE_OPENSSL 1
00009 #include      "libcouriertls.h"
00010 #include      <openssl/rand.h>
00011 #include      <openssl/x509.h>
00012 #include      "tlscache.h"
00013 #include      "rfc1035/rfc1035.h"
00014 #include      "soxwrap/soxwrap.h"
00015 #include      "random128/random128.h"
00016 #ifdef  getc
00017 #undef  getc
00018 #endif
00019 #include      <stdio.h>
00020 #include      <string.h>
00021 #include      <stdlib.h>
00022 #include      <ctype.h>
00023 #include      <netdb.h>
00024 #if HAVE_DIRENT_H
00025 #include <dirent.h>
00026 #define NAMLEN(dirent) strlen((dirent)->d_name)
00027 #else
00028 #define dirent direct
00029 #define NAMLEN(dirent) (dirent)->d_namlen
00030 #if HAVE_SYS_NDIR_H
00031 #include <sys/ndir.h>
00032 #endif
00033 #if HAVE_SYS_DIR_H
00034 #include <sys/dir.h>
00035 #endif
00036 #if HAVE_NDIR_H
00037 #include <ndir.h>
00038 #endif
00039 #endif
00040 #if    HAVE_UNISTD_H
00041 #include      <unistd.h>
00042 #endif
00043 #if    HAVE_FCNTL_H
00044 #include      <fcntl.h>
00045 #endif
00046 #include      <errno.h>
00047 #if    HAVE_SYS_TYPES_H
00048 #include      <sys/types.h>
00049 #endif
00050 #if    HAVE_SYS_STAT_H
00051 #include      <sys/stat.h>
00052 #endif
00053 #include      <sys/socket.h>
00054 #include      <arpa/inet.h>
00055 
00056 #include      <sys/time.h>
00057 
00058 /***** TODO *****/
00059 
00060 /* #define TLSCACHEDEBUG */
00061 
00062 static const char *safe_getenv(const struct tls_info *info, const char *n)
00063 {
00064        const char *v=(*info->getconfigvar)(n, info->app_data);
00065 
00066        if (!v)       v="";
00067        return (v);
00068 }
00069 
00070 static int get_peer_verify_level(const struct tls_info *info)
00071 {
00072        int peer_verify_level=SSL_VERIFY_PEER;
00073               /* SSL_VERIFY_NONE */
00074               /* SSL_VERIFY_PEER */
00075               /* SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */
00076        const char *s=safe_getenv(info, "TLS_VERIFYPEER");
00077 
00078        if (info->peer_verify_domain)
00079               return SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00080 
00081        switch (*s)   {
00082        case 'n':
00083        case 'N':            /* NONE */
00084               peer_verify_level=SSL_VERIFY_NONE;
00085               break;
00086        case 'p':
00087        case 'P':            /* PEER */
00088               peer_verify_level=SSL_VERIFY_PEER;
00089               break;
00090        case 'r':
00091        case 'R':            /* REQUIREPEER */
00092               peer_verify_level=
00093                      SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
00094               break;
00095        }
00096        return (peer_verify_level);
00097 }
00098 
00099 static int ssl_verify_callback(int goodcert, X509_STORE_CTX *x509)
00100 {
00101        SSL *ssl=
00102               X509_STORE_CTX_get_ex_data(x509,
00103                                       SSL_get_ex_data_X509_STORE_CTX_idx()
00104                                       );
00105        struct tls_info *info=SSL_get_app_data(ssl);
00106 
00107        if (info->peer_verify_domain || get_peer_verify_level(info))
00108        {
00109               if (!goodcert)
00110                      return (0);
00111 
00112               info->certificate_verified=1;
00113        }
00114 
00115        return (1);
00116 }
00117 
00118 static int verifypeer(const struct tls_info *info, SSL *ssl)
00119 {
00120        X509 *x=NULL;
00121        X509_NAME *subj=NULL;
00122        int nentries, j;
00123        char domain[256];
00124        char *p;
00125        char errmsg[1000];
00126 
00127        if (!info->peer_verify_domain)
00128               return (1);
00129 
00130        if (info->isserver)
00131        {
00132               x=SSL_get_peer_certificate(ssl);
00133 
00134               if (x)
00135                      subj=X509_get_subject_name(x);
00136        }
00137        else
00138        {
00139               STACK_OF(X509) *peer_cert_chain=SSL_get_peer_cert_chain(ssl);
00140 
00141               if (peer_cert_chain && peer_cert_chain->stack.num > 0)
00142               {
00143                      X509 *xx=(X509 *)peer_cert_chain->stack.data[0];
00144 
00145                      if (xx)
00146                             subj=X509_get_subject_name(xx);
00147               }
00148        }
00149 
00150        
00151        nentries=0;
00152        if (subj)
00153               nentries=X509_NAME_entry_count(subj);
00154 
00155        domain[0]=0;
00156        for (j=0; j<nentries; j++)
00157        {
00158               const char *obj_name;
00159               X509_NAME_ENTRY *e;
00160               ASN1_OBJECT *o;
00161               ASN1_STRING *d;
00162 
00163               int dlen;
00164               unsigned char *ddata;
00165 
00166               e=X509_NAME_get_entry(subj, j);
00167               if (!e)
00168                      continue;
00169 
00170               o=X509_NAME_ENTRY_get_object(e);
00171               d=X509_NAME_ENTRY_get_data(e);
00172 
00173               if (!o || !d)
00174                      continue;
00175 
00176               obj_name=OBJ_nid2sn(OBJ_obj2nid(o));
00177 
00178               dlen=ASN1_STRING_length(d);
00179               ddata=ASN1_STRING_data(d);
00180 
00181               if (strcasecmp(obj_name, "CN") == 0)
00182               {
00183                      if (dlen >= sizeof(domain)-1)
00184                             dlen=sizeof(domain)-1;
00185 
00186                      memcpy(domain, ddata, dlen);
00187                      domain[dlen]=0;
00188               }
00189        }
00190 
00191        if (x)
00192               X509_free(x);
00193        p=domain;
00194 
00195        if (*p == '*')
00196        {
00197               int    pl, l;
00198 
00199               pl=strlen(++p);
00200               l=strlen(info->peer_verify_domain);
00201 
00202               if (*p == '.' && pl <= l &&
00203                   strcasecmp(info->peer_verify_domain+l-pl, p) == 0)
00204                      return (1);
00205        }
00206        else if (strcasecmp(info->peer_verify_domain, p) == 0)
00207               return (1);
00208 
00209        strcpy(errmsg, "couriertls: Mismatched SSL certificate: CN=");
00210        strcat(errmsg, domain);
00211        strcat(errmsg, " (expected ");
00212        strncat(errmsg, info->peer_verify_domain, 256);
00213        strcat(errmsg, ")");
00214        (*info->tls_err_msg)(errmsg, info->app_data);
00215        return (0);
00216 }
00217 
00218 #ifndef NO_RSA
00219 
00220 static RSA *rsa_callback(SSL *s, int export, int keylength)
00221 {
00222        return (RSA_generate_key(keylength,RSA_F4,NULL,NULL));
00223 }
00224 
00225 #endif
00226 
00227 static void nonsslerror(const struct tls_info *info, const char *pfix)
00228 {
00229        char errmsg[256];
00230 
00231        strcpy(errmsg, "couriertls: ");
00232        strncat(errmsg, pfix, 200);
00233        strcat(errmsg, ": ");
00234        strncat(errmsg, strerror(errno), 255 - strlen(errmsg));
00235 
00236        (*info->tls_err_msg)(errmsg, info->app_data);
00237 }
00238 
00239 static void sslerror(const struct tls_info *info, const char *pfix, int rc)
00240 {
00241        char errmsg[256];
00242        char errmsgbuf2[300];
00243        int errnum=ERR_get_error();
00244 
00245        if (errnum == 0)
00246        {
00247               if (rc == 0)
00248               {
00249                      (*info->tls_err_msg)("DEBUG: Unexpected SSL connection shutdown.",
00250                                         info->app_data);
00251                      return;
00252               }
00253 
00254               nonsslerror(info, pfix);
00255               return;
00256        }
00257 
00258        ERR_error_string_n(errnum, errmsg, sizeof(errmsg)-1);
00259 
00260        errmsg[sizeof(errmsg)-1]=0;
00261 
00262        strcpy(errmsgbuf2, "couriertls: ");
00263        strncat(errmsgbuf2, pfix, 200);
00264        strcat(errmsgbuf2, ": ");
00265        strncat(errmsgbuf2, errmsg, 299 - strlen(errmsgbuf2));
00266 
00267        (*info->tls_err_msg)(errmsgbuf2, info->app_data);
00268 }
00269 
00270 static void init_session_cache(struct tls_info *, SSL_CTX *);
00271 
00272 static int process_rsacertfile(SSL_CTX *ctx, const char *filename)
00273 {
00274 #ifndef       NO_RSA
00275 
00276        const struct tls_info *info=SSL_CTX_get_app_data(ctx);
00277 
00278        SSL_CTX_set_tmp_rsa_callback(ctx, rsa_callback);
00279 
00280        if(!SSL_CTX_use_certificate_chain_file(ctx, filename))
00281        {
00282               sslerror(info, filename, -1);
00283               return (0);
00284        }
00285 
00286        if(!SSL_CTX_use_RSAPrivateKey_file(ctx, filename, SSL_FILETYPE_PEM))
00287        {
00288               sslerror(info, filename, -1);
00289               return (0);
00290        }
00291 #endif
00292        return (1);
00293 }
00294 
00295 
00296 static int process_dhcertfile(SSL_CTX *ctx, const char *filename)
00297 {
00298 #ifndef       NO_DH
00299 
00300        const struct tls_info *info=SSL_CTX_get_app_data(ctx);
00301        BIO    *bio;
00302        DH     *dh;
00303        int    cert_done=0;
00304 
00305        if(!SSL_CTX_use_certificate_chain_file(ctx, filename))
00306        {
00307               sslerror(info, filename, -1);
00308               return (0);
00309        }
00310 
00311        if ((bio=BIO_new_file(filename, "r")) != 0)
00312        {
00313               if ((dh=PEM_read_bio_DHparams(bio, NULL, NULL, NULL)) != 0)
00314               {
00315                      SSL_CTX_set_tmp_dh(ctx, dh);
00316                      cert_done=1;
00317                      DH_free(dh);
00318               }
00319               else
00320                      sslerror(info, filename, -1);
00321               BIO_free(bio);
00322        }
00323        else
00324               sslerror(info, filename, -1);
00325 
00326        if (!cert_done)
00327        {
00328               (*info->tls_err_msg)("couriertls: DH init failed!",
00329                                  info->app_data);
00330 
00331               return (0);
00332        }
00333 
00334        if(!SSL_CTX_use_PrivateKey_file(ctx, filename, SSL_FILETYPE_PEM))
00335        {
00336               sslerror(info, filename, -1);
00337               return (0);
00338        }
00339 #endif
00340        return (1);
00341 }
00342 
00343 static int process_certfile(SSL_CTX *ctx, const char *certfile, const char *ip,
00344                          int (*func)(SSL_CTX *, const char *))
00345 {
00346        if (ip && *ip)
00347        {
00348               char *test_file;
00349 
00350               if (strncmp(ip, "::ffff:", 7) == 0 && strchr(ip, '.'))
00351                      return (process_certfile(ctx, certfile, ip+7, func));
00352 
00353               test_file= malloc(strlen(certfile)+strlen(ip)+2);
00354 
00355               strcpy(test_file, certfile);
00356               strcat(test_file, ".");
00357               strcat(test_file, ip);
00358 
00359               if (access(test_file, R_OK) == 0)
00360               {
00361                      int rc= (*func)(ctx, test_file);
00362 
00363                      free(test_file);
00364                      return rc;
00365               }
00366               free(test_file);
00367        }
00368 
00369        return (*func)(ctx, certfile);
00370 }
00371 
00372 static int client_cert_cb(ssl_handle ssl, X509 **x509, EVP_PKEY **pkey)
00373 {
00374        struct tls_info *info=(struct tls_info *)SSL_get_app_data(ssl);
00375        int i;
00376        const char *pem_cert;
00377        size_t pem_cert_size;
00378        STACK_OF(X509_NAME) *client_cas;
00379        int cert_num=0;
00380        int rc;
00381 
00382        if (info->getpemclientcert4ca == NULL)
00383               return 0;
00384 
00385        rc=0;
00386        client_cas=SSL_get_client_CA_list(ssl);
00387 
00388        if (info->loadpemclientcert4ca)
00389               (*info->loadpemclientcert4ca)(info->app_data);
00390 
00391        for (cert_num=0; (*info->getpemclientcert4ca)(cert_num, &pem_cert,
00392                                                 &pem_cert_size,
00393                                                 info->app_data);
00394             ++cert_num)
00395        {
00396               BIO *certbio;
00397               int err;
00398               X509 *x;
00399 
00400               ERR_clear_error();
00401 
00402               certbio=BIO_new_mem_buf((void *)pem_cert, pem_cert_size);
00403 
00404               if (!certbio)
00405               {
00406                      rc= -1;
00407                      break;
00408               }
00409 
00410               x=PEM_read_bio_X509(certbio, x509, NULL, NULL);
00411 
00412               if (!x)
00413               {
00414                      BIO_free(certbio);
00415                      continue;
00416               }
00417 
00418               for (i=0; client_cas && i<client_cas->stack.num; i++)
00419               {
00420                      X509_NAME *cert=(X509_NAME *)client_cas->stack.data[i];
00421 
00422                      if (X509_NAME_cmp(cert,
00423                                      x->cert_info->issuer) == 0)
00424                             break;
00425               }
00426 
00427               if (!client_cas || i >= client_cas->stack.num)
00428               {
00429                      BIO_free(certbio);
00430                      continue;
00431               }
00432 
00433               while ((x=PEM_read_bio_X509(certbio, NULL,
00434                                        NULL, 0)) != NULL)
00435               {
00436                      if (SSL_CTX_add_extra_chain_cert(SSL_get_SSL_CTX(ssl),
00437                                                   x)
00438                          != 1)
00439                      {
00440                             X509_free(x);
00441                             rc= -1;
00442                             break;
00443                      }
00444               }
00445 
00446               err = ERR_peek_last_error();
00447               if (rc || ERR_GET_LIB(err) != ERR_LIB_PEM ||
00448                   ERR_GET_REASON(err) != PEM_R_NO_START_LINE)
00449               {
00450                      BIO_free(certbio);
00451                      continue;
00452               }
00453               BIO_free(certbio);
00454 
00455               ERR_clear_error();
00456 
00457               certbio=BIO_new_mem_buf((void *)pem_cert, pem_cert_size);
00458 
00459               if (!certbio)
00460               {
00461                      rc= -1;
00462                      break;
00463               }
00464 
00465               if (!PEM_read_bio_PrivateKey(certbio, pkey, NULL, NULL))
00466               {
00467                      BIO_free(certbio);
00468                      continue;
00469               }
00470 
00471               BIO_free(certbio);
00472               rc=1;
00473               break;
00474        }
00475        ERR_clear_error();
00476        (*info->releasepemclientcert4ca)(info->app_data);
00477        return rc;
00478 }
00479 
00480 SSL_CTX *tls_create(int isserver, const struct tls_info *info)
00481 {
00482        SSL_CTX *ctx;
00483        const char *protocol=safe_getenv(info, "TLS_PROTOCOL");
00484        const char *ssl_cipher_list=safe_getenv(info, "TLS_CIPHER_LIST");
00485        int session_timeout=atoi(safe_getenv(info, "TLS_TIMEOUT"));
00486        const char *dhcertfile=safe_getenv(info, "TLS_DHCERTFILE");
00487        const char *certfile=safe_getenv(info, "TLS_CERTFILE");
00488        const char *s;
00489        struct stat stat_buf;
00490        const char *peer_cert_dir=NULL;
00491        const char *peer_cert_file=NULL;
00492        int n;
00493        struct tls_info *info_copy;
00494 
00495        if (!*ssl_cipher_list)
00496               ssl_cipher_list=NULL;
00497 
00498        if (!*dhcertfile)
00499               dhcertfile=NULL;
00500 
00501        if (!*certfile)
00502               certfile=NULL;
00503 
00504        s=safe_getenv(info, "TLS_TRUSTCERTS");
00505        if (s && stat(s, &stat_buf) == 0)
00506        {
00507               if (S_ISDIR(stat_buf.st_mode))
00508                      peer_cert_dir=s;
00509               else
00510                      peer_cert_file=s;
00511        }
00512        else if (info->peer_verify_domain)
00513        {
00514               errno=ENOENT;
00515               nonsslerror(info, "TLS_TRUSTCERTS not set");
00516               return (NULL);
00517        }
00518 
00519        {
00520               static int first=1;
00521 
00522               if (first)
00523               {
00524                      first=0;
00525                      SSL_load_error_strings();
00526                      SSLeay_add_ssl_algorithms();
00527 
00528                      while (RAND_status() != 1)
00529                      {
00530                             const char *p=random128();
00531                             size_t l=strlen(p);
00532 
00533                             RAND_add(p, l, l/16);
00534                      }
00535               }
00536        }
00537 
00538 
00539        info_copy=malloc(sizeof(struct tls_info));
00540 
00541        if (info_copy == NULL)
00542        {
00543               nonsslerror(info, "malloc");
00544               return (NULL);
00545        }
00546 
00547        memcpy(info_copy, info, sizeof(*info_copy));
00548        info_copy->isserver=isserver;
00549        info_copy->certificate_verified=0;
00550 
00551        if (!protocol || !*protocol)
00552               protocol="SSL23";
00553 
00554        ctx=SSL_CTX_new(protocol && strcmp(protocol, "SSL3") == 0
00555                      ? SSLv3_method():
00556                      protocol && strcmp(protocol, "SSL23") == 0
00557                      ? SSLv23_method():
00558                      TLSv1_method());
00559 
00560        if (!ctx)
00561        {
00562               free(info_copy);
00563               nonsslerror(info, "SSL_CTX_NEW");
00564               return (0);
00565        }
00566        SSL_CTX_set_app_data(ctx, info_copy);
00567        SSL_CTX_set_options(ctx, SSL_OP_ALL);
00568 
00569        if (!ssl_cipher_list)
00570               ssl_cipher_list="SSLv3:TLSv1:HIGH:!LOW:!MEDIUM:!EXP:!NULL:!aNULL@STRENGTH";
00571 
00572        SSL_CTX_set_cipher_list(ctx, ssl_cipher_list);
00573        SSL_CTX_set_timeout(ctx, session_timeout);
00574 
00575        info_copy->tlscache=NULL;
00576        init_session_cache(info_copy, ctx);
00577 
00578 
00579        s = safe_getenv(info, "TCPLOCALIP");
00580 
00581        if (certfile && !process_certfile(ctx, certfile, s,
00582                                      process_rsacertfile))
00583        {
00584               tls_destroy(ctx);
00585               return (NULL);
00586        }
00587 
00588        if (dhcertfile && !process_certfile(ctx, dhcertfile, s,
00589                                        process_dhcertfile))
00590        {
00591               tls_destroy(ctx);
00592               return (NULL);
00593        }
00594 
00595        SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
00596 
00597        n=atoi(safe_getenv(info, "TLS_INTCACHESIZE"));
00598 
00599        if (n > 0)
00600               SSL_CTX_sess_set_cache_size(ctx, n);
00601 
00602        if (peer_cert_dir || peer_cert_file)
00603        {
00604               if ((!SSL_CTX_set_default_verify_paths(ctx))
00605                      || (!SSL_CTX_load_verify_locations(ctx, peer_cert_file,
00606                             peer_cert_dir)))
00607               {
00608                      sslerror(info, peer_cert_file ?
00609                              peer_cert_file:peer_cert_dir, -1);
00610                      tls_destroy(ctx);
00611                      return (0);
00612               }
00613 
00614               if (isserver && peer_cert_file)
00615               {
00616                      SSL_CTX_set_client_CA_list(ctx,
00617                                              SSL_load_client_CA_file
00618                                              (peer_cert_file));
00619               }
00620 
00621               if (isserver && peer_cert_dir)
00622               {
00623                      DIR *dirp;
00624                      struct dirent *de;
00625                      X509 *x;
00626 
00627                      dirp=opendir(peer_cert_dir);
00628                      while (dirp && (de=readdir(dirp)) != NULL)
00629                      {
00630                             const char *p;
00631                             char *q;
00632                             FILE *fp;
00633 
00634                             p=strrchr(de->d_name, '.');
00635                             if (!p || !p[1])
00636                                    continue;
00637                             while (*++p)
00638                             {
00639                                    if (strchr("0123456789", *p) == NULL)
00640                                           break;
00641                             }
00642                             if (*p)
00643                                    continue;
00644 
00645                             q=malloc(strlen(peer_cert_dir)
00646                                     +strlen(de->d_name) + 4);
00647                             if (!q)
00648                             {
00649                                    nonsslerror(info, "malloc");
00650                                    exit(1);
00651                             }
00652 
00653                             strcat(strcat(strcpy(q, peer_cert_dir),
00654                                          "/"), de->d_name);
00655 
00656                             fp=fopen(q, "r");
00657                             if (!fp)
00658                             {
00659                                    nonsslerror(info, q);
00660                                    exit(1);
00661                             }
00662                             free(q);
00663 
00664                             while ((x=PEM_read_X509(fp, NULL, NULL, NULL)))
00665                             {
00666                                    SSL_CTX_add_client_CA(ctx,x);
00667                                    X509_free(x);
00668                             }
00669                             fclose(fp);
00670                      }
00671                      if (dirp)
00672                             closedir(dirp);
00673                 }
00674        }
00675        SSL_CTX_set_verify(ctx, get_peer_verify_level(info),
00676                         ssl_verify_callback);
00677        if (!isserver)
00678               SSL_CTX_set_client_cert_cb(ctx, client_cert_cb);
00679        return (ctx);
00680 }
00681 
00682 void tls_destroy(SSL_CTX *ctx)
00683 {
00684        struct tls_info *info=SSL_CTX_get_app_data(ctx);
00685 
00686        SSL_CTX_flush_sessions(ctx, 0); /* OpenSSL bug, 2002-08-07 */
00687 
00688        SSL_CTX_free(ctx);
00689 
00690        if (info->tlscache)
00691        {
00692               tls_cache_close(info->tlscache);
00693               info->tlscache=NULL;
00694        }
00695        free(info);
00696 }
00697 
00698 static int cache_add(SSL *ssl, SSL_SESSION *sess);
00699 
00700 static SSL_SESSION *cache_get(SSL *ssl, unsigned char *id, int id_len,
00701                            int *copyflag);
00702 static void cache_del(SSL_CTX *ctx, SSL_SESSION *ssl);
00703 
00704 static void init_session_cache(struct tls_info *info, SSL_CTX *ctx)
00705 {
00706        const char *filename=safe_getenv(info, "TLS_CACHEFILE");
00707        const char *cachesize=safe_getenv(info, "TLS_CACHESIZE");
00708        off_t cachesize_l;
00709 
00710        if (!filename || !*filename)
00711        {
00712               SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
00713               return;
00714        }
00715 
00716        if (info->tlscache == NULL)
00717        {
00718               cachesize_l= cachesize ? (off_t)atol(cachesize):0;
00719 
00720               if (cachesize_l <= 0)
00721                      cachesize_l=512L * 1024;
00722               if ((info->tlscache=tls_cache_open(filename, cachesize_l))
00723                   == NULL)
00724               {
00725                      nonsslerror(info, filename);
00726                      return;
00727               }
00728        }
00729 
00730         SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
00731        SSL_CTX_sess_set_new_cb(ctx, cache_add);
00732        SSL_CTX_sess_set_get_cb(ctx, cache_get);
00733        SSL_CTX_sess_set_remove_cb(ctx, cache_del);
00734 }
00735 
00736 static int cache_add(SSL *ssl, SSL_SESSION *sess)
00737 {
00738        struct tls_info *info=SSL_get_app_data(ssl);
00739        unsigned char buffer[BUFSIZ];
00740        unsigned char *ucp;
00741        time_t timeout= (time_t)SSL_SESSION_get_time(sess)
00742               + SSL_SESSION_get_timeout(sess);
00743        void *session_id=(void *)sess->session_id;
00744        size_t session_id_len=sess->session_id_length;
00745        size_t sess_len=i2d_SSL_SESSION(sess, NULL);
00746 
00747        if (sizeof(timeout) + sizeof(session_id_len) + session_id_len +
00748            sess_len > sizeof(buffer))
00749        {
00750               fprintf(stderr, "WARN: starttls.c: buffer not big enough to cache SSL_SESSION\n");
00751               return (0);   /* Too big */
00752        }
00753 
00754        memcpy(buffer, &timeout, sizeof(timeout));
00755        memcpy(buffer+sizeof(timeout), &session_id_len,
00756               sizeof(session_id_len));
00757        memcpy(buffer+sizeof(timeout)+sizeof(session_id_len),
00758               session_id, session_id_len);
00759        ucp=buffer+sizeof(timeout)+
00760               sizeof(session_id_len)+session_id_len;
00761 
00762        i2d_SSL_SESSION(sess, &ucp);
00763        if (tls_cache_add(info->tlscache, (char *)buffer,
00764                        (size_t)(sizeof(timeout) +
00765                                sizeof(session_id_len) +
00766                                session_id_len + sess_len)))
00767               perror("ALERT: tls_cache_add: ");
00768 
00769 #ifdef TLSCACHEDEBUG
00770        fprintf(stderr, "INFO: TLSCACHE: added\n");
00771 #endif
00772        return 0;
00773 }
00774 
00775 struct walk_info {
00776        unsigned char *id;
00777        int id_len;
00778        int *copyflag;
00779        SSL_SESSION *ret;
00780        time_t now;
00781 };
00782 
00783 static int get_func(void *rec, size_t recsize,
00784                   int *doupdate, void *arg);
00785 
00786 static SSL_SESSION *cache_get(SSL *ssl, unsigned char *id, int id_len,
00787                            int *copyflag)
00788 {
00789        const struct tls_info *info=SSL_get_app_data(ssl);
00790        struct walk_info wi;
00791 
00792        wi.id=id;
00793        wi.id_len=id_len;
00794        wi.copyflag=copyflag;
00795        wi.ret=NULL;
00796        time(&wi.now);
00797        if (tls_cache_walk(info->tlscache, get_func, &wi) < 0)
00798               perror("ALERT: tls_cache_walk: ");
00799 
00800 #ifdef TLSCACHEDEBUG
00801        fprintf(stderr, "INFO: TLSCACHE: session %s\n",
00802               wi.ret ? "found":"not found");
00803 #endif
00804        if (wi.ret)
00805               SSL_set_session_id_context(ssl, id, id_len);
00806        return wi.ret;
00807 }
00808 
00809 static int get_func(void *rec, size_t recsize,
00810                   int *doupdate, void *arg)
00811 {
00812        unsigned char *recp=(unsigned char *)rec;
00813        struct walk_info *wi=(struct walk_info *)arg;
00814        time_t timeout;
00815        size_t session_id_len;
00816 
00817        unsigned char *sess;
00818 
00819        if (recsize < sizeof(timeout)+sizeof(session_id_len))
00820               return (0);
00821 
00822        memcpy(&timeout, recp, sizeof(timeout));
00823 
00824        if (timeout <= wi->now)
00825               return (0);
00826 
00827        memcpy(&session_id_len, recp + sizeof(timeout),
00828               sizeof(session_id_len));
00829 
00830        if (session_id_len != (size_t)wi->id_len ||
00831            memcmp(recp + sizeof(timeout) + sizeof(session_id_len),
00832                  wi->id, session_id_len))
00833               return (0);
00834 
00835        sess=recp + sizeof(timeout) + sizeof(session_id_len) + session_id_len;
00836 
00837        wi->ret=d2i_SSL_SESSION(NULL, (const unsigned char **)
00838                             &sess, recsize - sizeof(timeout) -
00839                             sizeof(session_id_len) - session_id_len);
00840 
00841        *wi->copyflag=0;
00842        return 1;
00843 }
00844 
00845 static int del_func(void *rec, size_t recsize,
00846                   int *doupdate, void *arg);
00847 
00848 static void cache_del(SSL_CTX *ctx, SSL_SESSION *sess)
00849 {
00850        const struct tls_info *info=SSL_CTX_get_app_data(ctx);
00851        struct walk_info wi;
00852 
00853        wi.now=0;
00854 
00855        wi.id=(unsigned char *)sess->session_id;
00856        wi.id_len=sess->session_id_length;
00857        if (tls_cache_walk(info->tlscache, del_func, &wi) < 0)
00858               perror("ALERT: tls_cache_walk: ");
00859 }
00860 
00861 static int del_func(void *rec, size_t recsize,
00862                   int *doupdate, void *arg)
00863 {
00864        unsigned char *recp=(unsigned char *)rec;
00865        struct walk_info *wi=(struct walk_info *)arg;
00866        time_t timeout;
00867        size_t session_id_len;
00868 
00869        if (recsize < sizeof(timeout)+sizeof(session_id_len))
00870               return (0);
00871 
00872        memcpy(&timeout, recp, sizeof(timeout));
00873 
00874        if (timeout <= wi->now)
00875               return (0);
00876 
00877        memcpy(&session_id_len, recp + sizeof(timeout),
00878               sizeof(session_id_len));
00879 
00880        if (session_id_len != (size_t)wi->id_len ||
00881            memcmp(recp + sizeof(timeout) + sizeof(session_id_len),
00882                  wi->id, session_id_len))
00883               return (0);
00884 
00885        timeout=0;
00886        memcpy(recp, &timeout, sizeof(timeout));
00887        *doupdate=1;
00888 #ifdef TLSCACHEDEBUG
00889        fprintf(stderr, "INFO: TLSCACHE: deleted\n");
00890 #endif
00891        return (1);
00892 }
00893 
00894 
00895 /* ----------------------------------------------------------------- */
00896 
00897 SSL *tls_connect(SSL_CTX *ctx, int fd)
00898 {
00899        struct tls_info *info=SSL_CTX_get_app_data(ctx);
00900        SSL *ssl;
00901        int rc;
00902 
00903        /*
00904        **  Initialize a tls_transfer_info object.
00905        */
00906 
00907        if (fcntl(fd, F_SETFL, O_NONBLOCK))
00908        {
00909               nonsslerror(info, "fcntl");
00910               return (NULL);
00911        }
00912 
00913 #ifdef  SO_KEEPALIVE
00914 
00915        {
00916        int    dummy;
00917 
00918               dummy=1;
00919 
00920               if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
00921                      (const char *)&dummy, sizeof(dummy)) < 0)
00922                 {
00923                         nonsslerror(info, "setsockopt");
00924                      return (NULL);
00925                 }
00926        }
00927 #endif
00928 
00929 #ifdef  SO_LINGER
00930        {
00931        struct linger l;
00932 
00933               l.l_onoff=0;
00934               l.l_linger=0;
00935 
00936               if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
00937                      (const char *)&l, sizeof(l)) < 0)
00938               {
00939                      nonsslerror(info, "setsockopt");
00940                      return (NULL);
00941               }
00942        }
00943 #endif
00944 
00945        if (!(ssl=SSL_new(ctx)))
00946        {
00947               sslerror(info, "SSL_new", -1);
00948               return (NULL);
00949        }
00950 
00951        SSL_set_app_data(ssl, info);
00952 
00953        SSL_set_fd(ssl, fd);
00954        info->accept_interrupted=0;
00955        info->connect_interrupted=0;
00956 
00957        if (info->isserver)
00958        {
00959               SSL_set_accept_state(ssl);
00960               if ((rc=SSL_accept(ssl)) > 0)
00961               {
00962                      if (!verifypeer(info, ssl))
00963                      {
00964                             tls_disconnect(ssl, fd);
00965                             return (NULL);
00966                      }
00967 
00968                      if (info->connect_callback != NULL &&
00969                          !(*info->connect_callback)(ssl, info->app_data))
00970                      {
00971                             tls_disconnect(ssl, fd);
00972                             return (NULL);
00973                      }
00974 
00975                      return ssl;
00976               }
00977               info->accept_interrupted=1;
00978        }
00979        else
00980        {
00981               SSL_set_connect_state(ssl);
00982 
00983               if ((rc=SSL_connect(ssl)) > 0)
00984               {
00985                      if (!verifypeer(info, ssl))
00986                      {
00987                             tls_disconnect(ssl, fd);
00988                             return (NULL);
00989                      }
00990 
00991                      if (info->connect_callback != NULL &&
00992                          !(*info->connect_callback)(ssl, info->app_data))
00993                      {
00994                             tls_disconnect(ssl, fd);
00995                             return (NULL);
00996                      }
00997                      return (ssl);
00998               }
00999               info->connect_interrupted=1;
01000        }
01001 
01002        switch (SSL_get_error(ssl, rc))    {
01003        case SSL_ERROR_WANT_WRITE:
01004        case SSL_ERROR_WANT_READ:
01005               break;
01006        default:
01007               sslerror(info, "connect", rc);
01008               tls_disconnect(ssl, fd);
01009               return NULL;
01010        }
01011 
01012        return (ssl);
01013 }
01014 
01015 void tls_disconnect(SSL *ssl, int fd)
01016 {
01017        fcntl(fd, F_SETFL, 0);
01018        SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
01019        SSL_free(ssl);
01020        ERR_remove_state(0);
01021 }
01022 
01023 /* --------------------------------------- */
01024 
01025 int    tls_transfer(struct tls_transfer_info *t, SSL *ssl, int fd,
01026                    fd_set *r, fd_set *w)
01027 {
01028        struct tls_info *info=SSL_get_app_data(ssl);
01029        int n;
01030 
01031        if (info->connect_interrupted)
01032        {
01033               n=SSL_connect(ssl);
01034 
01035               switch (SSL_get_error(ssl, n))     {
01036               case SSL_ERROR_NONE:
01037                      info->connect_interrupted=0;
01038                      break;
01039               case SSL_ERROR_WANT_WRITE:
01040                      FD_SET(fd, w);
01041                      return (1);
01042               case SSL_ERROR_WANT_READ:
01043                      FD_SET(fd, r);
01044                      return (1);
01045               default:
01046                      info->connect_interrupted=0;
01047                      t->shutdown=1;
01048                      sslerror(info, "connect", n);
01049                      return (-1);
01050               }
01051 
01052               if (!verifypeer(info, ssl))
01053               {
01054                      info->connect_interrupted=0;
01055                      t->shutdown=1;
01056                      return (-1);
01057               }
01058               if (info->connect_callback != NULL &&
01059                   !(*info->connect_callback)(ssl, info->app_data))
01060               {
01061                      info->connect_interrupted=0;
01062                      t->shutdown=1;
01063                      return (-1);
01064               }
01065        }
01066        else if (info->accept_interrupted)
01067        {
01068               n=SSL_accept(ssl);
01069 
01070               switch (SSL_get_error(ssl, n))     {
01071               case SSL_ERROR_NONE:
01072                      info->accept_interrupted=0;
01073                      break;
01074               case SSL_ERROR_WANT_WRITE:
01075                      FD_SET(fd, w);
01076                      return (1);
01077               case SSL_ERROR_WANT_READ:
01078                      FD_SET(fd, r);
01079                      return (1);
01080               default:
01081                      info->accept_interrupted=0;
01082                      t->shutdown=1;
01083                      sslerror(info, "accept", n);
01084                      return (-1);
01085               }
01086 
01087               if (!verifypeer(info, ssl))
01088               {
01089                      info->accept_interrupted=0;
01090                      t->shutdown=1;
01091                      return (-1);
01092               }
01093 
01094               if (info->connect_callback != NULL &&
01095                   !(*info->connect_callback)(ssl, info->app_data))
01096               {
01097                      info->accept_interrupted=0;
01098                      t->shutdown=1;
01099                      return (-1);
01100               }
01101        }
01102 
01103        if (t->shutdown)
01104               return -1;
01105 
01106        if (t->shutdown_interrupted && !t->read_interrupted &&
01107            !t->write_interrupted)
01108        {
01109               n=SSL_shutdown(ssl);
01110               if (n > 0)
01111               {
01112                      t->shutdown_interrupted=0;
01113                      t->shutdown=1;
01114                      return -1;
01115               }
01116 
01117               switch (SSL_get_error(ssl, n))     {
01118               case SSL_ERROR_WANT_WRITE:
01119                      FD_SET(fd, w);
01120                      break;
01121               case SSL_ERROR_WANT_READ:
01122                      FD_SET(fd, r);
01123                      break;
01124               default:
01125                      t->shutdown_interrupted=0;
01126                      t->shutdown= -1;
01127                      return -1;
01128               }
01129               return 1;
01130        }
01131 
01132        if (!t->write_interrupted && t->readleft > 0)
01133        {
01134               n=SSL_read(ssl, t->readptr, t->readleft);
01135 
01136               switch (SSL_get_error(ssl, n))     {
01137               case SSL_ERROR_NONE:
01138                      break;
01139               case SSL_ERROR_WANT_WRITE:
01140                      t->read_interrupted=1;
01141                      FD_SET(fd, w);
01142                      return (1);
01143               case SSL_ERROR_WANT_READ:
01144                      FD_SET(fd, r);
01145                      n=0;
01146                      break;
01147               case SSL_ERROR_WANT_X509_LOOKUP:
01148                      n=0;
01149                      break;
01150               case SSL_ERROR_ZERO_RETURN:
01151                      t->shutdown=1;
01152                      return (-1);
01153               default:
01154                      sslerror(info, "read", n);
01155                      return (-1);
01156               }
01157               t->read_interrupted=0;
01158               t->readptr += n;
01159               t->readleft -= n;
01160 
01161               if (n > 0)
01162                      return (0);
01163        }
01164 
01165        if (!t->read_interrupted && t->writeleft > 0)
01166        {
01167               n=SSL_write(ssl, t->writeptr, t->writeleft);
01168 
01169               switch (SSL_get_error(ssl, n))     {
01170               case SSL_ERROR_NONE:
01171                      break;
01172               case SSL_ERROR_WANT_WRITE:
01173                      FD_SET(fd, w);
01174                      n=0;
01175                      break;
01176               case SSL_ERROR_WANT_READ:
01177                      t->write_interrupted=1;
01178                      FD_SET(fd, r);
01179                      return (1);
01180               case SSL_ERROR_ZERO_RETURN:
01181                      t->shutdown=1;
01182                      return (-1);
01183               case SSL_ERROR_WANT_X509_LOOKUP:
01184                      n=0;
01185                      break;
01186               default:
01187                      return (-1);
01188               }
01189               t->write_interrupted=0;
01190               t->writeptr += n;
01191               t->writeleft -= n;
01192 
01193               if (n > 0)
01194                      return (0);
01195        }
01196 
01197        return (1);
01198 }
01199 
01200 int tls_connecting(SSL *ssl)
01201 {
01202        struct tls_info *info=(struct tls_info *)SSL_get_app_data(ssl);
01203 
01204        return info->accept_interrupted || info->connect_interrupted;
01205 }
01206 
01207 int tls_certificate_verified(ssl_handle ssl)
01208 {
01209        struct tls_info *info=(struct tls_info *)SSL_get_app_data(ssl);
01210 
01211        return info->certificate_verified;
01212 }
01213 
01214 #define MAXDOMAINSIZE       256
01215 
01216 static time_t asn1toTime(ASN1_TIME *asn1Time)
01217 {
01218        struct tm tm;
01219        int offset;
01220 
01221        if (asn1Time == NULL || asn1Time->length < 13)
01222               return 0;
01223 
01224        memset(&tm, 0, sizeof(tm));
01225 
01226 #define N2(n) ((asn1Time->data[n]-'0')*10 + asn1Time->data[(n)+1]-'0')
01227 
01228 #define CPY(f,n) (tm.f=N2(n))
01229 
01230        CPY(tm_year,0);
01231 
01232        if(tm.tm_year < 50)
01233               tm.tm_year += 100; /* Sux */
01234 
01235        CPY(tm_mon, 2);
01236        --tm.tm_mon;
01237        CPY(tm_mday, 4);
01238        CPY(tm_hour, 6);
01239        CPY(tm_min, 8);
01240        CPY(tm_sec, 10);
01241 
01242        offset=0;
01243 
01244        if (asn1Time->data[12] != 'Z')
01245        {
01246               if (asn1Time->length < 17)
01247                      return 0;
01248 
01249               offset=N2(13)*3600+N2(15)*60;
01250 
01251               if (asn1Time->data[12] == '-')
01252                      offset= -offset;
01253        }
01254 
01255 #undef N2
01256 #undef CPY
01257 
01258        return mktime(&tm)-offset;
01259 }
01260 
01261 
01262 static void dump_x509(X509 *x509,
01263                     void (*dump_func)(const char *, int cnt, void *),
01264                     void *dump_arg)
01265 {
01266        X509_NAME *subj=X509_get_subject_name(x509);
01267        int nentries, j;
01268        time_t timestamp;
01269        static const char gcc_shutup[]="%Y-%m-%d %H:%M:%S";
01270 
01271        if (!subj)
01272               return;
01273 
01274        (*dump_func)("Subject:\n", -1, dump_arg);
01275 
01276        nentries=X509_NAME_entry_count(subj);
01277        for (j=0; j<nentries; j++)
01278        {
01279               const char *obj_name;
01280               X509_NAME_ENTRY *e;
01281               ASN1_OBJECT *o;
01282               ASN1_STRING *d;
01283 
01284               int dlen;
01285               unsigned char *ddata;
01286 
01287               e=X509_NAME_get_entry(subj, j);
01288               if (!e)
01289                      continue;
01290 
01291               o=X509_NAME_ENTRY_get_object(e);
01292               d=X509_NAME_ENTRY_get_data(e);
01293 
01294               if (!o || !d)
01295                      continue;
01296 
01297               obj_name=OBJ_nid2sn(OBJ_obj2nid(o));
01298 
01299               dlen=ASN1_STRING_length(d);
01300               ddata=ASN1_STRING_data(d);
01301        
01302               (*dump_func)("   ", -1, dump_arg);
01303               (*dump_func)(obj_name, -1, dump_arg);
01304               (*dump_func)("=", 1, dump_arg);
01305               (*dump_func)((const char *)ddata, dlen, dump_arg);
01306               (*dump_func)("\n", 1, dump_arg);
01307               
01308        }
01309        (*dump_func)("\n", 1, dump_arg);
01310 
01311        timestamp=asn1toTime(X509_get_notBefore(x509));
01312 
01313        if (timestamp)
01314        {
01315               struct tm *tm=localtime(&timestamp);
01316               char buffer[500];
01317 
01318               buffer[strftime(buffer, sizeof(buffer)-1, gcc_shutup,
01319                             tm)]=0;
01320 
01321               (*dump_func)("Not-Before: ", -1, dump_arg);
01322               (*dump_func)(buffer, -1, dump_arg);
01323               (*dump_func)("\n", 1, dump_arg);
01324        }
01325 
01326        timestamp=asn1toTime(X509_get_notAfter(x509));
01327        if (timestamp)
01328        {
01329               struct tm *tm=localtime(&timestamp);
01330               char buffer[500];
01331 
01332               buffer[strftime(buffer, sizeof(buffer)-1, gcc_shutup,
01333                             tm)]=0;
01334 
01335               (*dump_func)("Not-After: ", -1, dump_arg);
01336               (*dump_func)(buffer, -1, dump_arg);
01337               (*dump_func)("\n", 1, dump_arg);
01338        }
01339 }
01340 
01341 void tls_dump_connection_info(ssl_handle ssl,
01342                            int server,
01343                            void (*dump_func)(const char *, int cnt, void *),
01344                            void *dump_arg)
01345 {
01346        const SSL_CIPHER *cipher;
01347 
01348        {
01349               STACK_OF(X509) *peer_cert_chain=SSL_get_peer_cert_chain(ssl);
01350               int i;
01351 
01352               if (server)
01353               {
01354                      X509 *x=SSL_get_peer_certificate(ssl);
01355 
01356                      if (x)
01357                      {
01358                             dump_x509(x, dump_func, dump_arg);
01359                             X509_free(x);
01360                      }
01361               }
01362 
01363               for (i=0; peer_cert_chain && i<peer_cert_chain->stack.num; i++)
01364                      dump_x509((X509 *)peer_cert_chain->stack.data[i],
01365                               dump_func, dump_arg);
01366        }
01367 
01368        cipher=SSL_get_current_cipher(ssl);
01369 
01370        if (cipher)
01371        {
01372               const char *c;
01373 
01374               c=SSL_CIPHER_get_version(cipher);
01375               if (c)
01376               {
01377                      (*dump_func)("Version: ", -1, dump_arg);
01378                      (*dump_func)(c, -1, dump_arg);
01379                      (*dump_func)("\n", 1, dump_arg);
01380               }
01381 
01382               {
01383                      char buf[10];
01384 
01385                      (*dump_func)("Bits: ", -1, dump_arg);
01386 
01387                      snprintf(buf, sizeof(buf), "%d",
01388                              SSL_CIPHER_get_bits(cipher, NULL));
01389                      buf[sizeof(buf)-1]=0;
01390 
01391                      (*dump_func)(buf, -1, dump_arg);
01392                      (*dump_func)("\n", 1, dump_arg);
01393               }
01394 
01395               c=SSL_CIPHER_get_name(cipher);
01396 
01397               if (c)
01398               {
01399                      (*dump_func)("Cipher: ", -1, dump_arg);
01400                      (*dump_func)(c, -1, dump_arg);
01401                      (*dump_func)("\n", 1, dump_arg);
01402               }
01403        }
01404 }
01405 
01406 char *tls_get_encryption_desc(ssl_handle ssl)
01407 {
01408        char protocolbuf[256];
01409        const SSL_CIPHER *cipher;
01410        const char *c, *d;
01411 
01412        cipher=SSL_get_current_cipher(ssl);
01413 
01414        c=cipher ? SSL_CIPHER_get_version(cipher):NULL;
01415        d=cipher ? SSL_CIPHER_get_name(cipher):NULL;
01416 
01417        snprintf(protocolbuf, sizeof(protocolbuf),
01418                "%s,%dbits,%s",
01419                c ? c:"unknown",
01420                cipher ? SSL_CIPHER_get_bits(cipher, NULL):0,
01421                d ? d:"unknown");
01422        protocolbuf[sizeof(protocolbuf)-1]=0;
01423        return strdup(protocolbuf);
01424 }
01425 
01426 
01427 /* ------------------- */
01428 
01429 int tls_validate_pem_cert(const char *buf, size_t buf_size)
01430 {
01431        int rc;
01432        BIO *certbio;
01433        int err;
01434        EVP_PKEY *pk;
01435        X509 *x;
01436 
01437        ERR_clear_error();
01438 
01439        rc=0;
01440        certbio=BIO_new_mem_buf((void *)buf, buf_size);
01441 
01442        if (!certbio)
01443               return (0);
01444 
01445        x=PEM_read_bio_X509(certbio, NULL, NULL, NULL);
01446 
01447        if (x)
01448        {
01449               X509_free(x);
01450 
01451               while ((x=PEM_read_bio_X509(certbio, NULL, NULL, NULL)) != NULL)
01452                      X509_free(x);
01453 
01454               err = ERR_peek_last_error();
01455                 if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
01456                   ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
01457               {
01458                      rc=1;
01459               }
01460        }
01461 
01462        ERR_clear_error();
01463        BIO_free(certbio);
01464 
01465        certbio=BIO_new_mem_buf((void *)buf, buf_size);
01466 
01467        if (!certbio)
01468               return (0);
01469 
01470        if (!(pk=PEM_read_bio_PrivateKey(certbio, NULL, NULL, NULL)))
01471        {
01472               BIO_free(certbio);
01473               ERR_clear_error();
01474               return 0;
01475        }
01476 
01477        EVP_PKEY_free(pk);
01478        return rc;
01479 }
01480 
01481 static size_t conv_name_to_rfc2553(const char *p, char *q)
01482 {
01483 #define PUTC(c) if (q) *q++=(c); ++n
01484 
01485        size_t n=0;
01486        const char *sep="";
01487 
01488        while (*p)
01489        {
01490               if (*p == '/')
01491               {
01492                      ++p;
01493                      continue;
01494               }
01495 
01496               while (*sep)
01497               {
01498                      PUTC(*sep);
01499                      ++sep;
01500               }
01501               sep=",";
01502 
01503               while (*p && *p != '/')
01504               {
01505                      if (*p == '\\' && p[1])
01506                             ++p;
01507                      if (*p == '\\' || *p == ',')
01508                      {
01509                             PUTC('\\');
01510                      }
01511                      PUTC(*p);
01512                      ++p;
01513               }
01514        }
01515        PUTC(0);
01516 #undef PUTC
01517 
01518        return n;
01519 }
01520 
01521 char *tls_cert_name(const char *buf, size_t buf_size)
01522 {
01523        BIO *certbio;
01524        char *p, *q;
01525        X509 *x;
01526        size_t cnt;
01527 
01528        certbio=BIO_new_mem_buf((void *)buf, buf_size);
01529 
01530        if (!certbio)
01531        {
01532               ERR_clear_error();
01533               return (0);
01534        }
01535 
01536        x=PEM_read_bio_X509(certbio, NULL, NULL, NULL);
01537        p=0;
01538        q=0;
01539 
01540        if (x)
01541        {
01542               p=X509_NAME_oneline(x->cert_info->subject, NULL, 0);
01543               X509_free(x);
01544        }
01545        ERR_clear_error();
01546        BIO_free(certbio);
01547 
01548        if (p)
01549        {
01550               cnt=conv_name_to_rfc2553(p, NULL);
01551 
01552               q=malloc(cnt);
01553 
01554               if (q)
01555                      conv_name_to_rfc2553(p, q);
01556               free(p);
01557        }
01558 
01559        return q;
01560 }