1 36 37 import java.io.*; 38 import java.nio.*; 39 import java.nio.channels.*; 40 import javax.net.ssl.*; 41 import javax.net.ssl.SSLEngineResult.*; 42 43 101 class ChannelIOSecure extends ChannelIO { 102 103 private SSLEngine sslEngine = null; 104 105 private int appBBSize; 106 private int netBBSize; 107 108 117 private ByteBuffer inNetBB; 118 private ByteBuffer outNetBB; 119 120 125 private static ByteBuffer hsBB = ByteBuffer.allocate(0); 126 127 130 private ByteBuffer fileChannelBB = null; 131 132 141 private HandshakeStatus initialHSStatus; 142 private boolean initialHSComplete; 143 144 148 private boolean shutdown = false; 149 150 153 protected ChannelIOSecure(SocketChannel sc, boolean blocking, 154 SSLContext sslc) throws IOException { 155 super(sc, blocking); 156 157 162 sslEngine = sslc.createSSLEngine(); 163 sslEngine.setUseClientMode(false); 164 initialHSStatus = HandshakeStatus.NEED_UNWRAP; 165 initialHSComplete = false; 166 167 netBBSize = sslEngine.getSession().getPacketBufferSize(); 171 inNetBB = ByteBuffer.allocate(netBBSize); 172 outNetBB = ByteBuffer.allocate(netBBSize); 173 outNetBB.position(0); 174 outNetBB.limit(0); 175 } 176 177 184 static ChannelIOSecure getInstance(SocketChannel sc, boolean blocking, 185 SSLContext sslc) throws IOException { 186 187 ChannelIOSecure cio = new ChannelIOSecure(sc, blocking, sslc); 188 189 cio.appBBSize = cio.sslEngine.getSession().getApplicationBufferSize(); 193 cio.requestBB = ByteBuffer.allocate(cio.appBBSize); 194 195 return cio; 196 } 197 198 202 protected void resizeRequestBB() { 203 resizeRequestBB(appBBSize); 204 } 205 206 209 private void resizeResponseBB() { 210 ByteBuffer bb = ByteBuffer.allocate(netBBSize); 211 inNetBB.flip(); 212 bb.put(inNetBB); 213 inNetBB = bb; 214 } 215 216 221 private boolean tryFlush(ByteBuffer bb) throws IOException { 222 super.write(bb); 223 return !bb.hasRemaining(); 224 } 225 226 232 boolean doHandshake() throws IOException { 233 return doHandshake(null); 234 } 235 236 253 boolean doHandshake(SelectionKey sk) throws IOException { 254 255 SSLEngineResult result; 256 257 if (initialHSComplete) { 258 return initialHSComplete; 259 } 260 261 265 if (outNetBB.hasRemaining()) { 266 267 if (!tryFlush(outNetBB)) { 268 return false; 269 } 270 271 273 switch (initialHSStatus) { 274 275 278 case FINISHED: 279 initialHSComplete = true; 280 282 case NEED_UNWRAP: 283 if (sk != null) { 284 sk.interestOps(SelectionKey.OP_READ); 285 } 286 break; 287 } 288 289 return initialHSComplete; 290 } 291 292 293 switch (initialHSStatus) { 294 295 case NEED_UNWRAP: 296 if (sc.read(inNetBB) == -1) { 297 sslEngine.closeInbound(); 298 return initialHSComplete; 299 } 300 301 needIO: 302 while (initialHSStatus == HandshakeStatus.NEED_UNWRAP) { 303 resizeRequestBB(); inNetBB.flip(); 305 result = sslEngine.unwrap(inNetBB, requestBB); 306 inNetBB.compact(); 307 308 initialHSStatus = result.getHandshakeStatus(); 309 310 switch (result.getStatus()) { 311 312 case OK: 313 switch (initialHSStatus) { 314 case NOT_HANDSHAKING: 315 throw new IOException( 316 "Not handshaking during initial handshake"); 317 318 case NEED_TASK: 319 initialHSStatus = doTasks(); 320 break; 321 322 case FINISHED: 323 initialHSComplete = true; 324 break needIO; 325 } 326 327 break; 328 329 case BUFFER_UNDERFLOW: 330 netBBSize = sslEngine.getSession().getPacketBufferSize(); 332 if (netBBSize > inNetBB.capacity()) { 333 resizeResponseBB(); 334 } 335 336 339 if (sk != null) { 340 sk.interestOps(SelectionKey.OP_READ); 341 } 342 break needIO; 343 344 case BUFFER_OVERFLOW: 345 appBBSize = 347 sslEngine.getSession().getApplicationBufferSize(); 348 break; 349 350 default: throw new IOException("Received" + result.getStatus() + 352 "during initial handshaking"); 353 } 354 } 356 359 if (initialHSStatus != HandshakeStatus.NEED_WRAP) { 360 break; 361 } 362 363 365 case NEED_WRAP: 366 369 outNetBB.clear(); 370 result = sslEngine.wrap(hsBB, outNetBB); 371 outNetBB.flip(); 372 373 initialHSStatus = result.getHandshakeStatus(); 374 375 switch (result.getStatus()) { 376 case OK: 377 378 if (initialHSStatus == HandshakeStatus.NEED_TASK) { 379 initialHSStatus = doTasks(); 380 } 381 382 if (sk != null) { 383 sk.interestOps(SelectionKey.OP_WRITE); 384 } 385 386 break; 387 388 default: throw new IOException("Received" + result.getStatus() + 390 "during initial handshaking"); 391 } 392 break; 393 394 default: throw new RuntimeException ("Invalid Handshaking State" + 396 initialHSStatus); 397 } 399 return initialHSComplete; 400 } 401 402 405 private SSLEngineResult.HandshakeStatus doTasks() { 406 407 Runnable runnable; 408 409 413 while ((runnable = sslEngine.getDelegatedTask()) != null) { 414 runnable.run(); 415 } 416 return sslEngine.getHandshakeStatus(); 417 } 418 419 428 int read() throws IOException { 429 SSLEngineResult result; 430 431 if (!initialHSComplete) { 432 throw new IllegalStateException (); 433 } 434 435 int pos = requestBB.position(); 436 437 if (sc.read(inNetBB) == -1) { 438 sslEngine.closeInbound(); return -1; 440 } 441 442 do { 443 resizeRequestBB(); inNetBB.flip(); 445 result = sslEngine.unwrap(inNetBB, requestBB); 446 inNetBB.compact(); 447 448 454 switch (result.getStatus()) { 455 456 case BUFFER_OVERFLOW: 457 appBBSize = sslEngine.getSession().getApplicationBufferSize(); 459 break; 460 461 case BUFFER_UNDERFLOW: 462 netBBSize = sslEngine.getSession().getPacketBufferSize(); 464 if (netBBSize > inNetBB.capacity()) { 465 resizeResponseBB(); 466 467 break; } 469 case OK: 470 if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { 471 doTasks(); 472 } 473 break; 474 475 default: 476 throw new IOException("sslEngine error during data read: " + 477 result.getStatus()); 478 } 479 } while ((inNetBB.position() != 0) && 480 result.getStatus() != Status.BUFFER_UNDERFLOW); 481 482 return (requestBB.position() - pos); 483 } 484 485 488 int write(ByteBuffer src) throws IOException { 489 490 if (!initialHSComplete) { 491 throw new IllegalStateException (); 492 } 493 494 return doWrite(src); 495 } 496 497 505 private int doWrite(ByteBuffer src) throws IOException { 506 int retValue = 0; 507 508 if (outNetBB.hasRemaining() && !tryFlush(outNetBB)) { 509 return retValue; 510 } 511 512 515 outNetBB.clear(); 516 517 SSLEngineResult result = sslEngine.wrap(src, outNetBB); 518 retValue = result.bytesConsumed(); 519 520 outNetBB.flip(); 521 522 switch (result.getStatus()) { 523 524 case OK: 525 if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { 526 doTasks(); 527 } 528 break; 529 530 default: 531 throw new IOException("sslEngine error during data write: " + 532 result.getStatus()); 533 } 534 535 540 if (outNetBB.hasRemaining()) { 541 tryFlush(outNetBB); 542 } 543 544 return retValue; 545 } 546 547 559 long transferTo(FileChannel fc, long pos, long len) throws IOException { 560 561 if (!initialHSComplete) { 562 throw new IllegalStateException (); 563 } 564 565 if (fileChannelBB == null) { 566 fileChannelBB = ByteBuffer.allocate(appBBSize); 567 fileChannelBB.limit(0); 568 } 569 570 fileChannelBB.compact(); 571 int fileRead = fc.read(fileChannelBB); 572 fileChannelBB.flip(); 573 574 579 doWrite(fileChannelBB); 580 581 return fileRead; 582 } 583 584 589 boolean dataFlush() throws IOException { 590 boolean fileFlushed = true; 591 592 if ((fileChannelBB != null) && fileChannelBB.hasRemaining()) { 593 doWrite(fileChannelBB); 594 fileFlushed = !fileChannelBB.hasRemaining(); 595 } else if (outNetBB.hasRemaining()) { 596 tryFlush(outNetBB); 597 } 598 599 return (fileFlushed && !outNetBB.hasRemaining()); 600 } 601 602 610 boolean shutdown() throws IOException { 611 612 if (!shutdown) { 613 sslEngine.closeOutbound(); 614 shutdown = true; 615 } 616 617 if (outNetBB.hasRemaining() && tryFlush(outNetBB)) { 618 return false; 619 } 620 621 625 outNetBB.clear(); 626 SSLEngineResult result = sslEngine.wrap(hsBB, outNetBB); 627 if (result.getStatus() != Status.CLOSED) { 628 throw new SSLException("Improper close state"); 629 } 630 outNetBB.flip(); 631 632 636 if (outNetBB.hasRemaining()) { 637 tryFlush(outNetBB); 638 } 639 640 return (!outNetBB.hasRemaining() && 641 (result.getHandshakeStatus() != HandshakeStatus.NEED_WRAP)); 642 } 643 644 647 } 648 | Popular Tags |