• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

SSLNetVConnection.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 #include "ink_config.h"
00024 #include "P_Net.h"
00025 #include "P_SSLNextProtocolSet.h"
00026 #include "P_SSLUtils.h"
00027 
00028 #define SSL_READ_ERROR_NONE       0
00029 #define SSL_READ_ERROR            1
00030 #define SSL_READ_READY            2
00031 #define SSL_READ_COMPLETE         3
00032 #define SSL_READ_WOULD_BLOCK      4
00033 #define SSL_READ_EOS              5
00034 #define SSL_HANDSHAKE_WANT_READ   6
00035 #define SSL_HANDSHAKE_WANT_WRITE  7
00036 #define SSL_HANDSHAKE_WANT_ACCEPT 8
00037 #define SSL_HANDSHAKE_WANT_CONNECT 9
00038 #define SSL_WRITE_WOULD_BLOCK     10
00039 
00040 ClassAllocator<SSLNetVConnection> sslNetVCAllocator("sslNetVCAllocator");
00041 
00042 //
00043 // Private
00044 //
00045 
00046 static SSL *
00047 make_ssl_connection(SSL_CTX * ctx, SSLNetVConnection * netvc)
00048 {
00049   SSL * ssl;
00050 
00051   if (likely(ssl = SSL_new(ctx))) {
00052     SSL_set_fd(ssl, netvc->get_socket());
00053     SSL_set_app_data(ssl, netvc);
00054   }
00055 
00056   return ssl;
00057 }
00058 
00059 static void
00060 debug_certificate_name(const char * msg, X509_NAME * name)
00061 {
00062   BIO * bio;
00063 
00064   if (name == NULL) {
00065     return;
00066   }
00067 
00068   bio = BIO_new(BIO_s_mem());
00069   if (bio == NULL) {
00070     return;
00071   }
00072 
00073   if (X509_NAME_print_ex(bio, name, 0 /* indent */, XN_FLAG_ONELINE) > 0) {
00074     long len;
00075     char * ptr;
00076     len = BIO_get_mem_data(bio, &ptr);
00077     Debug("ssl", "%s %.*s", msg, (int)len, ptr);
00078   }
00079 
00080   BIO_free(bio);
00081 }
00082 
00083 static inline int
00084 do_SSL_write(SSL * ssl, void *buf, int size)
00085 {
00086   int r = 0;
00087   do {
00088     // need to check into SSL error handling
00089     // to see if this is good enough.
00090     r = SSL_write(ssl, (const char *) buf, size);
00091     if (r >= 0)
00092       return r;
00093     else
00094       r = -errno;
00095   } while (r == -EINTR || r == -ENOBUFS || r == -ENOMEM);
00096 
00097   return r;
00098 }
00099 
00100 
00101 static int
00102 ssl_read_from_net(SSLNetVConnection * sslvc, EThread * lthread, int64_t &ret)
00103 {
00104   NetState *s = &sslvc->read;
00105   MIOBufferAccessor & buf = s->vio.buffer;
00106   IOBufferBlock *b = buf.writer()->first_write_block();
00107   int event = SSL_READ_ERROR_NONE;
00108   int64_t bytes_read;
00109   int64_t block_write_avail;
00110   int sslErr = SSL_ERROR_NONE;
00111 
00112   for (bytes_read = 0; (b != 0) && (sslErr == SSL_ERROR_NONE); b = b->next) {
00113     block_write_avail = b->write_avail();
00114 
00115     Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] b->write_avail()=%" PRId64, block_write_avail);
00116 
00117     int64_t offset = 0;
00118     // while can be replaced with if - need to test what works faster with openssl
00119     while (block_write_avail > 0) {
00120       int rres = SSL_read(sslvc->ssl, b->end() + offset, (int)block_write_avail);
00121 
00122       Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] rres=%d", rres);
00123 
00124       sslErr = SSL_get_error(sslvc->ssl, rres);
00125       switch (sslErr) {
00126       case SSL_ERROR_NONE:
00127 
00128 #if DEBUG
00129         SSLDebugBufferPrint("ssl_buff", b->end() + offset, rres, "SSL Read");
00130 #endif
00131 
00132         ink_assert(rres);
00133 
00134         bytes_read += rres;
00135         offset += rres;
00136         block_write_avail -= rres;
00137         ink_assert(block_write_avail >= 0);
00138 
00139         continue;
00140 
00141       case SSL_ERROR_WANT_WRITE:
00142         event = SSL_WRITE_WOULD_BLOCK;
00143         SSL_INCREMENT_DYN_STAT(ssl_error_want_write);
00144         Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(write)");
00145         break;
00146       case SSL_ERROR_WANT_READ:
00147         event = SSL_READ_WOULD_BLOCK;
00148         SSL_INCREMENT_DYN_STAT(ssl_error_want_read);
00149         Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(read)");
00150         break;
00151       case SSL_ERROR_WANT_X509_LOOKUP:
00152         event = SSL_READ_WOULD_BLOCK;
00153         SSL_INCREMENT_DYN_STAT(ssl_error_want_x509_lookup);
00154         Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_WOULD_BLOCK(read/x509 lookup)");
00155         break;
00156       case SSL_ERROR_SYSCALL:
00157         SSL_INCREMENT_DYN_STAT(ssl_error_syscall);
00158         if (rres != 0) {
00159           // not EOF
00160           event = SSL_READ_ERROR;
00161           ret = errno;
00162           Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SYSCALL, underlying IO error: %s", strerror(errno));
00163         } else {
00164           // then EOF observed, treat it as EOS
00165           event = SSL_READ_EOS;
00166           //Error("[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_SYSCALL, EOF observed violating SSL protocol");
00167         }
00168         break;
00169       case SSL_ERROR_ZERO_RETURN:
00170         event = SSL_READ_EOS;
00171         SSL_INCREMENT_DYN_STAT(ssl_error_zero_return);
00172         Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net] SSL_ERROR_ZERO_RETURN");
00173         break;
00174       case SSL_ERROR_SSL:
00175       default:
00176         event = SSL_READ_ERROR;
00177         ret = errno;
00178         SSL_INCREMENT_DYN_STAT(ssl_error_ssl);
00179         Debug("ssl.error", "[SSL_NetVConnection::ssl_read_from_net]");
00180         break;
00181       }                         // switch
00182       break;
00183     }                           // while( block_write_avail > 0 )
00184   }                             // for ( bytes_read = 0; (b != 0); b = b->next)
00185 
00186   if (bytes_read > 0) {
00187     Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] bytes_read=%" PRId64, bytes_read);
00188     buf.writer()->fill(bytes_read);
00189     s->vio.ndone += bytes_read;
00190     sslvc->netActivity(lthread);
00191 
00192     ret = bytes_read;
00193 
00194     if (s->vio.ntodo() <= 0) {
00195       event = SSL_READ_COMPLETE;
00196     } else {
00197       event = SSL_READ_READY;
00198     }
00199   } else                        // if( bytes_read > 0 )
00200   {
00201 #if defined (_DEBUG)
00202     if (bytes_read == 0) {
00203       Debug("ssl", "[SSL_NetVConnection::ssl_read_from_net] bytes_read == 0");
00204     }
00205 #endif
00206   }
00207   return (event);
00208 
00209 }
00210 
00211 
00212 //changed by YTS Team, yamsat
00213 void
00214 SSLNetVConnection::net_read_io(NetHandler *nh, EThread *lthread)
00215 {
00216   int ret;
00217   int64_t r = 0;
00218   int64_t bytes = 0;
00219   NetState *s = &this->read;
00220   MIOBufferAccessor &buf = s->vio.buffer;
00221   int64_t ntodo = s->vio.ntodo();
00222 
00223   if (sslClientRenegotiationAbort == true) {
00224     this->read.triggered = 0;
00225     readSignalError(nh, (int)r);
00226     Debug("ssl", "[SSLNetVConnection::net_read_io] client renegotiation setting read signal error");
00227     return;
00228   }
00229 
00230   MUTEX_TRY_LOCK_FOR(lock, s->vio.mutex, lthread, s->vio._cont);
00231   if (!lock) {
00232     readReschedule(nh);
00233     return;
00234   }
00235   // If it is not enabled, lower its priority.  This allows
00236   // a fast connection to speed match a slower connection by
00237   // shifting down in priority even if it could read.
00238   if (!s->enabled || s->vio.op != VIO::READ) {
00239     read_disable(nh, this);
00240     return;
00241   }
00242 
00243   ink_assert(buf.writer());
00244 
00245   // This function will always return true unless
00246   // vc is an SSLNetVConnection.
00247   if (!getSSLHandShakeComplete()) {
00248     int err;
00249 
00250     if (getSSLClientConnection()) {
00251       ret = sslStartHandShake(SSL_EVENT_CLIENT, err);
00252     } else {
00253       ret = sslStartHandShake(SSL_EVENT_SERVER, err);
00254     }
00255 
00256     if (ret == EVENT_ERROR) {
00257       this->read.triggered = 0;
00258       readSignalError(nh, err);
00259     } else if (ret == SSL_HANDSHAKE_WANT_READ || ret == SSL_HANDSHAKE_WANT_ACCEPT) {
00260       read.triggered = 0;
00261       nh->read_ready_list.remove(this);
00262       readReschedule(nh);
00263     } else if (ret == SSL_HANDSHAKE_WANT_CONNECT || ret == SSL_HANDSHAKE_WANT_WRITE) {
00264       write.triggered = 0;
00265       nh->write_ready_list.remove(this);
00266       writeReschedule(nh);
00267     } else if (ret == EVENT_DONE) {
00268       // If this was driven by a zero length read, signal complete when
00269       // the handshake is complete. Otherwise set up for continuing read
00270       // operations.
00271       if (ntodo <= 0) {
00272         readSignalDone(VC_EVENT_READ_COMPLETE, nh);
00273       } else {
00274         read.triggered = 1;
00275         if (read.enabled)
00276           nh->read_ready_list.in_or_enqueue(this);
00277       }
00278     } else
00279       readReschedule(nh);
00280     return;
00281   }
00282 
00283   // If there is nothing to do or no space available, disable connection
00284   if (ntodo <= 0 || !buf.writer()->write_avail()) {
00285     read_disable(nh, this);
00286     return;
00287   }
00288 
00289   // not sure if this do-while loop is really needed here, please replace this comment if you know
00290   do {
00291     ret = ssl_read_from_net(this, lthread, r);
00292     if (ret == SSL_READ_READY || ret == SSL_READ_ERROR_NONE) {
00293       bytes += r;
00294     }
00295     ink_assert(bytes >= 0);
00296   } while ((ret == SSL_READ_READY && bytes == 0) || ret == SSL_READ_ERROR_NONE);
00297 
00298   if (bytes > 0) {
00299     if (ret == SSL_READ_WOULD_BLOCK || ret == SSL_READ_READY) {
00300       if (readSignalAndUpdate(VC_EVENT_READ_READY) != EVENT_CONT) {
00301         Debug("ssl", "ssl_read_from_net, readSignal != EVENT_CONT");
00302         return;
00303       }
00304     }
00305   }
00306 
00307   switch (ret) {
00308   case SSL_READ_ERROR_NONE:
00309   case SSL_READ_READY:
00310     readReschedule(nh);
00311     return;
00312     break;
00313   case SSL_WRITE_WOULD_BLOCK:
00314   case SSL_READ_WOULD_BLOCK:
00315     if (lock.m.m_ptr != s->vio.mutex.m_ptr) {
00316       Debug("ssl", "ssl_read_from_net, mutex switched");
00317       if (ret == SSL_READ_WOULD_BLOCK)
00318         readReschedule(nh);
00319       else
00320         writeReschedule(nh);
00321       return;
00322     }
00323     // reset the trigger and remove from the ready queue
00324     // we will need to be retriggered to read from this socket again
00325     read.triggered = 0;
00326     nh->read_ready_list.remove(this);
00327     Debug("ssl", "read_from_net, read finished - would block");
00328 #ifdef TS_USE_PORT
00329     if (ret == SSL_READ_WOULD_BLOCK)
00330       readReschedule(nh);
00331     else
00332       writeReschedule(nh);
00333 #endif
00334     break;
00335 
00336   case SSL_READ_EOS:
00337     // close the connection if we have SSL_READ_EOS, this is the return value from ssl_read_from_net() if we get an SSL_ERROR_ZERO_RETURN from SSL_get_error()
00338     // SSL_ERROR_ZERO_RETURN means that the origin server closed the SSL connection
00339     read.triggered = 0;
00340     readSignalDone(VC_EVENT_EOS, nh);
00341 
00342     if (bytes > 0) {
00343       Debug("ssl", "read_from_net, read finished - EOS");
00344     } else {
00345       Debug("ssl", "read_from_net, read finished - 0 useful bytes read, bytes used by SSL layer");
00346     }
00347     break;
00348   case SSL_READ_COMPLETE:
00349     readSignalDone(VC_EVENT_READ_COMPLETE, nh);
00350     Debug("ssl", "read_from_net, read finished - signal done");
00351     break;
00352   case SSL_READ_ERROR:
00353     this->read.triggered = 0;
00354     readSignalError(nh, (int)r);
00355     Debug("ssl", "read_from_net, read finished - read error");
00356     break;
00357   }
00358 
00359 }
00360 
00361 
00362 int64_t
00363 SSLNetVConnection::load_buffer_and_write(int64_t towrite, int64_t &wattempted, int64_t &total_wrote, MIOBufferAccessor & buf, int &needs)
00364 {
00365   ProxyMutex *mutex = this_ethread()->mutex;
00366   int64_t r = 0;
00367   int64_t l = 0;
00368 
00369   // XXX Rather than dealing with the block directly, we should use the IOBufferReader API.
00370   int64_t offset = buf.reader()->start_offset;
00371   IOBufferBlock *b = buf.reader()->block;
00372 
00373   do {
00374     // check if we have done this block
00375     l = b->read_avail();
00376     l -= offset;
00377     if (l <= 0) {
00378       offset = -l;
00379       b = b->next;
00380       continue;
00381     }
00382     // check if to amount to write exceeds that in this buffer
00383     int64_t wavail = towrite - total_wrote;
00384 
00385     if (l > wavail) {
00386       l = wavail;
00387     }
00388 
00389     // TS-2365: If the SSL max record size is set and we have
00390     // more data than that, break this into smaller write
00391     // operations.
00392     int64_t orig_l = l;
00393     if (SSLConfigParams::ssl_maxrecord > 0 && l > SSLConfigParams::ssl_maxrecord) {
00394         l = SSLConfigParams::ssl_maxrecord;
00395     }
00396 
00397     if (!l) {
00398       break;
00399     }
00400 
00401     wattempted = l;
00402     total_wrote += l;
00403     Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, before do_SSL_write, l=%" PRId64", towrite=%" PRId64", b=%p",
00404           l, towrite, b);
00405     r = do_SSL_write(ssl, b->start() + offset, (int)l);
00406     if (r == l) {
00407       wattempted = total_wrote;
00408     }
00409     if (l == orig_l) {
00410         // on to the next block
00411         offset = 0;
00412         b = b->next;
00413     } else {
00414         offset += l;
00415     }
00416 
00417     Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite,Number of bytes written=%" PRId64" , total=%" PRId64"", r, total_wrote);
00418     NET_DEBUG_COUNT_DYN_STAT(net_calls_to_write_stat, 1);
00419   } while (r == l && total_wrote < towrite && b);
00420 
00421   if (r > 0) {
00422     if (total_wrote != wattempted) {
00423       Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, wrote some bytes, but not all requested.");
00424       // I'm not sure how this could happen. We should have tried and hit an EAGAIN.
00425       needs |= EVENTIO_WRITE;
00426       return (r);
00427     } else {
00428       Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, write successful.");
00429       return (total_wrote);
00430     }
00431   } else {
00432     int err = SSL_get_error(ssl, (int)r);
00433 
00434     switch (err) {
00435     case SSL_ERROR_NONE:
00436       Debug("ssl", "SSL_write-SSL_ERROR_NONE");
00437       break;
00438     case SSL_ERROR_WANT_READ:
00439       needs |= EVENTIO_READ;
00440       r = -EAGAIN;
00441       SSL_INCREMENT_DYN_STAT(ssl_error_want_read);
00442       Debug("ssl.error", "SSL_write-SSL_ERROR_WANT_READ");
00443       break;
00444     case SSL_ERROR_WANT_WRITE:
00445     case SSL_ERROR_WANT_X509_LOOKUP: {
00446       if (SSL_ERROR_WANT_WRITE == err)
00447         SSL_INCREMENT_DYN_STAT(ssl_error_want_write);
00448       else if (SSL_ERROR_WANT_X509_LOOKUP == err)
00449         SSL_INCREMENT_DYN_STAT(ssl_error_want_x509_lookup);
00450 
00451       needs |= EVENTIO_WRITE;
00452       r = -EAGAIN;
00453       Debug("ssl.error", "SSL_write-SSL_ERROR_WANT_WRITE");
00454       break;
00455     }
00456     case SSL_ERROR_SYSCALL:
00457       r = -errno;
00458       SSL_INCREMENT_DYN_STAT(ssl_error_syscall);
00459       Debug("ssl.error", "SSL_write-SSL_ERROR_SYSCALL");
00460       break;
00461       // end of stream
00462     case SSL_ERROR_ZERO_RETURN:
00463       r = -errno;
00464       SSL_INCREMENT_DYN_STAT(ssl_error_zero_return);
00465       Debug("ssl.error", "SSL_write-SSL_ERROR_ZERO_RETURN");
00466       break;
00467     case SSL_ERROR_SSL:
00468     default:
00469       r = -errno;
00470       SSL_INCREMENT_DYN_STAT(ssl_error_ssl);
00471       Debug("ssl.error", "SSL_write-SSL_ERROR_SSL");
00472       break;
00473     }
00474     return (r);
00475   }
00476 }
00477 
00478 SSLNetVConnection::SSLNetVConnection():
00479   sslHandShakeComplete(false),
00480   sslClientConnection(false),
00481   sslClientRenegotiationAbort(false),
00482   npnSet(NULL),
00483   npnEndpoint(NULL)
00484 {
00485   ssl = NULL;
00486   sslHandshakeBeginTime = 0;
00487 }
00488 
00489 void
00490 SSLNetVConnection::free(EThread * t) {
00491   NET_SUM_GLOBAL_DYN_STAT(net_connections_currently_open_stat, -1);
00492   got_remote_addr = 0;
00493   got_local_addr = 0;
00494   read.vio.mutex.clear();
00495   write.vio.mutex.clear();
00496   this->mutex.clear();
00497   flags = 0;
00498   SET_CONTINUATION_HANDLER(this, (SSLNetVConnHandler) & SSLNetVConnection::startEvent);
00499   nh = NULL;
00500   read.triggered = 0;
00501   write.triggered = 0;
00502   options.reset();
00503   closed = 0;
00504   ink_assert(con.fd == NO_FD);
00505   if (ssl != NULL) {
00506     /*if (sslHandShakeComplete)
00507        SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); */
00508     SSL_free(ssl);
00509     ssl = NULL;
00510   }
00511   sslHandShakeComplete = false;
00512   sslClientConnection = false;
00513   sslClientRenegotiationAbort = false;
00514   npnSet = NULL;
00515   npnEndpoint= NULL;
00516 
00517   if (from_accept_thread) {
00518     sslNetVCAllocator.free(this);  
00519   } else {
00520     THREAD_FREE(this, sslNetVCAllocator, t);
00521   }
00522 }
00523 
00524 int
00525 SSLNetVConnection::sslStartHandShake(int event, int &err)
00526 {
00527 
00528   switch (event) {
00529   case SSL_EVENT_SERVER:
00530     if (this->ssl == NULL) {
00531       SSLCertificateConfig::scoped_config lookup;
00532 
00533       // Attach the default SSL_CTX to this SSL session. The default context is never going to be able
00534       // to negotiate a SSL session, but it's enough to trampoline us into the SNI callback where we
00535       // can select the right server certificate.
00536       this->ssl = make_ssl_connection(lookup->defaultContext(), this);
00537     }
00538 
00539     if (this->ssl == NULL) {
00540       SSLErrorVC(this, "failed to create SSL server session");
00541       return EVENT_ERROR;
00542     }
00543 
00544     return sslServerHandShakeEvent(err);
00545 
00546   case SSL_EVENT_CLIENT:
00547     if (this->ssl == NULL) {
00548       this->ssl = make_ssl_connection(ssl_NetProcessor.client_ctx, this);
00549     }
00550 
00551     if (this->ssl == NULL) {
00552       SSLErrorVC(this, "failed to create SSL client session");
00553       return EVENT_ERROR;
00554     }
00555 
00556     return sslClientHandShakeEvent(err);
00557 
00558   default:
00559     ink_assert(0);
00560     return EVENT_ERROR;
00561   }
00562 
00563 }
00564 
00565 int
00566 SSLNetVConnection::sslServerHandShakeEvent(int &err)
00567 {
00568   int ret = SSL_accept(ssl);
00569   int ssl_error = SSL_get_error(ssl, ret);
00570 
00571   if (ssl_error != SSL_ERROR_NONE) {
00572     err = errno;
00573     SSLDebugVC(this,"SSL handshake error: %s (%d), errno=%d", SSLErrorName(ssl_error), ssl_error, err);
00574   }
00575 
00576   switch (ssl_error) {
00577   case SSL_ERROR_NONE:
00578     if (is_debug_tag_set("ssl")) {
00579       X509 * cert = SSL_get_peer_certificate(ssl);
00580 
00581       Debug("ssl", "SSL server handshake completed successfully");
00582       if (cert) {
00583         debug_certificate_name("client certificate subject CN is", X509_get_subject_name(cert));
00584         debug_certificate_name("client certificate issuer CN is", X509_get_issuer_name(cert));
00585         X509_free(cert);
00586       }
00587     }
00588 
00589     sslHandShakeComplete = true;
00590 
00591     if (sslHandshakeBeginTime) {
00592       const ink_hrtime ssl_handshake_time = ink_get_hrtime() - sslHandshakeBeginTime;
00593       Debug("ssl", "ssl handshake time:%" PRId64, ssl_handshake_time);
00594       sslHandshakeBeginTime = 0;
00595       SSL_INCREMENT_DYN_STAT_EX(ssl_total_handshake_time_stat, ssl_handshake_time);
00596       SSL_INCREMENT_DYN_STAT(ssl_total_success_handshake_count_stat);
00597     }
00598 
00599     {
00600       const unsigned char * proto = NULL;
00601       unsigned len = 0;
00602 
00603       // If it's possible to negotiate both NPN and ALPN, then ALPN
00604       // is preferred since it is the server's preference.  The server
00605       // preference would not be meaningful if we let the client
00606       // preference have priority.
00607 
00608 #if TS_USE_TLS_ALPN
00609       SSL_get0_alpn_selected(ssl, &proto, &len);
00610 #endif /* TS_USE_TLS_ALPN */
00611 
00612 #if TS_USE_TLS_NPN
00613       if (len == 0) {
00614         SSL_get0_next_proto_negotiated(ssl, &proto, &len);
00615       }
00616 #endif /* TS_USE_TLS_NPN */
00617 
00618       if (len) {
00619         // If there's no NPN set, we should not have done this negotiation.
00620         ink_assert(this->npnSet != NULL);
00621 
00622         this->npnEndpoint = this->npnSet->findEndpoint(proto, len);
00623         this->npnSet = NULL;
00624 
00625         if (this->npnEndpoint == NULL) {
00626           Error("failed to find registered SSL endpoint for '%.*s'", (int)len, (const char *)proto);
00627           return EVENT_ERROR;
00628         }
00629 
00630         Debug("ssl", "client selected next protocol '%.*s'", len, proto);
00631       } else {
00632         Debug("ssl", "client did not select a next protocol");
00633       }
00634     }
00635 
00636     return EVENT_DONE;
00637 
00638   case SSL_ERROR_WANT_CONNECT:
00639     return SSL_HANDSHAKE_WANT_CONNECT;
00640 
00641   case SSL_ERROR_WANT_WRITE:
00642     return SSL_HANDSHAKE_WANT_WRITE;
00643 
00644   case SSL_ERROR_WANT_READ:
00645     return SSL_HANDSHAKE_WANT_READ;
00646 
00647   case SSL_ERROR_WANT_ACCEPT:
00648   case SSL_ERROR_WANT_X509_LOOKUP:
00649     return EVENT_CONT;
00650 
00651   case SSL_ERROR_ZERO_RETURN:
00652   case SSL_ERROR_SYSCALL:
00653   case SSL_ERROR_SSL:
00654   default:
00655     return EVENT_ERROR;
00656   }
00657 
00658 }
00659 
00660 
00661 int
00662 SSLNetVConnection::sslClientHandShakeEvent(int &err)
00663 {
00664   int ret;
00665 
00666 #if TS_USE_TLS_SNI
00667   if (options.sni_servername) {
00668     if (SSL_set_tlsext_host_name(ssl, options.sni_servername)) {
00669       Debug("ssl", "using SNI name '%s' for client handshake", options.sni_servername);
00670     } else {
00671       Debug("ssl.error","failed to set SNI name '%s' for client handshake", options.sni_servername);
00672       SSL_INCREMENT_DYN_STAT(ssl_sni_name_set_failure);
00673     }
00674   }
00675 #endif
00676 
00677   ret = SSL_connect(ssl);
00678   switch (SSL_get_error(ssl, ret)) {
00679   case SSL_ERROR_NONE:
00680     if (is_debug_tag_set("ssl")) {
00681       X509 * cert = SSL_get_peer_certificate(ssl);
00682 
00683       Debug("ssl", "SSL client handshake completed successfully");
00684       // if the handshake is complete and write is enabled reschedule the write
00685       if (closed == 0 && write.enabled)
00686         writeReschedule(nh);
00687       if (cert) {
00688         debug_certificate_name("server certificate subject CN is", X509_get_subject_name(cert));
00689         debug_certificate_name("server certificate issuer CN is", X509_get_issuer_name(cert));
00690         X509_free(cert);
00691       }
00692     }
00693 
00694     sslHandShakeComplete = true;
00695     return EVENT_DONE;
00696 
00697   case SSL_ERROR_WANT_WRITE:
00698     Debug("ssl.error", "SSLNetVConnection::sslClientHandShakeEvent, SSL_ERROR_WANT_WRITE");
00699     SSL_INCREMENT_DYN_STAT(ssl_error_want_write);
00700     return SSL_HANDSHAKE_WANT_WRITE;
00701 
00702   case SSL_ERROR_WANT_READ:
00703     SSL_INCREMENT_DYN_STAT(ssl_error_want_read);
00704     Debug("ssl.error", "SSLNetVConnection::sslClientHandShakeEvent, SSL_ERROR_WANT_READ");
00705     return SSL_HANDSHAKE_WANT_READ;
00706 
00707   case SSL_ERROR_WANT_X509_LOOKUP:
00708     SSL_INCREMENT_DYN_STAT(ssl_error_want_x509_lookup);
00709     Debug("ssl.error", "SSLNetVConnection::sslClientHandShakeEvent, SSL_ERROR_WANT_X509_LOOKUP");
00710     break;
00711 
00712   case SSL_ERROR_WANT_ACCEPT:
00713     return SSL_HANDSHAKE_WANT_ACCEPT;
00714 
00715   case SSL_ERROR_WANT_CONNECT:
00716     break;
00717 
00718   case SSL_ERROR_ZERO_RETURN:
00719     SSL_INCREMENT_DYN_STAT(ssl_error_zero_return);
00720     Debug("ssl.error", "SSLNetVConnection::sslClientHandShakeEvent, EOS");
00721     return EVENT_ERROR;
00722 
00723   case SSL_ERROR_SYSCALL:
00724     err = errno;
00725     SSL_INCREMENT_DYN_STAT(ssl_error_syscall);
00726     Debug("ssl.error", "SSLNetVConnection::sslClientHandShakeEvent, syscall");
00727     return EVENT_ERROR;
00728     break;
00729 
00730 
00731   case SSL_ERROR_SSL:
00732   default:
00733     err = errno;
00734     SSL_INCREMENT_DYN_STAT(ssl_error_ssl);
00735     Debug("ssl.error", "SSLNetVConnection::sslClientHandShakeEvent, SSL_ERROR_SSL");
00736     return EVENT_ERROR;
00737     break;
00738 
00739   }
00740   return EVENT_CONT;
00741 
00742 }
00743 
00744 void
00745 SSLNetVConnection::registerNextProtocolSet(const SSLNextProtocolSet * s)
00746 {
00747   ink_release_assert(this->npnSet == NULL);
00748   this->npnSet = s;
00749 }
00750 
00751 // NextProtocolNegotiation TLS extension callback. The NPN extension
00752 // allows the client to select a preferred protocol, so all we have
00753 // to do here is tell them what out protocol set is.
00754 int
00755 SSLNetVConnection::advertise_next_protocol(SSL *ssl, const unsigned char **out, unsigned int *outlen,
00756                                            void * /*arg ATS_UNUSED */)
00757 {
00758   SSLNetVConnection * netvc = (SSLNetVConnection *)SSL_get_app_data(ssl);
00759 
00760   ink_release_assert(netvc != NULL);
00761 
00762   if (netvc->npnSet && netvc->npnSet->advertiseProtocols(out, outlen)) {
00763     // Successful return tells OpenSSL to advertise.
00764     return SSL_TLSEXT_ERR_OK;
00765   }
00766 
00767   return SSL_TLSEXT_ERR_NOACK;
00768 }
00769 
00770 // ALPN TLS extension callback. Given the client's set of offered
00771 // protocols, we have to select a protocol to use for this session.
00772 int
00773 SSLNetVConnection::select_next_protocol(SSL * ssl, const unsigned char ** out, unsigned char * outlen, const unsigned char * in ATS_UNUSED, unsigned inlen ATS_UNUSED, void *)
00774 {
00775   SSLNetVConnection * netvc = (SSLNetVConnection *)SSL_get_app_data(ssl);
00776   const unsigned char * npn = NULL;
00777   unsigned npnsz = 0;
00778 
00779   ink_release_assert(netvc != NULL);
00780 
00781   if (netvc->npnSet && netvc->npnSet->advertiseProtocols(&npn, &npnsz)) {
00782     // SSL_select_next_proto chooses the first server-offered protocol that appears in the clients protocol set, ie. the
00783     // server selects the protocol. This is a n^2 search, so it's preferable to keep the protocol set short.
00784 
00785 #if HAVE_SSL_SELECT_NEXT_PROTO
00786     if (SSL_select_next_proto((unsigned char **)out, outlen, npn, npnsz, in, inlen) == OPENSSL_NPN_NEGOTIATED) {
00787       Debug("ssl", "selected ALPN protocol %.*s", (int)(*outlen), *out);
00788       return SSL_TLSEXT_ERR_OK;
00789     }
00790 #endif /* HAVE_SSL_SELECT_NEXT_PROTO */
00791   }
00792 
00793   *out = NULL;
00794   *outlen = 0;
00795   return SSL_TLSEXT_ERR_NOACK;
00796 }

Generated by  doxygen 1.7.1