server-arg.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* NOCW */
  2. /* demos/bio/server-arg.c */
  3. /*
  4. * A minimal program to serve an SSL connection. It uses blocking. It use the
  5. * SSL_CONF API with the command line. cc -I../../include server-arg.c
  6. * -L../.. -lssl -lcrypto -ldl
  7. */
  8. #include <stdio.h>
  9. #include <signal.h>
  10. #include <openssl/err.h>
  11. #include <openssl/ssl.h>
  12. int main(int argc, char *argv[])
  13. {
  14. char *port = "*:4433";
  15. BIO *ssl_bio, *tmp;
  16. SSL_CTX *ctx;
  17. SSL_CONF_CTX *cctx;
  18. char buf[512];
  19. BIO *in = NULL;
  20. int ret = 1, i;
  21. char **args = argv + 1;
  22. int nargs = argc - 1;
  23. SSL_load_error_strings();
  24. /* Add ciphers and message digests */
  25. OpenSSL_add_ssl_algorithms();
  26. ctx = SSL_CTX_new(TLS_server_method());
  27. cctx = SSL_CONF_CTX_new();
  28. SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
  29. SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
  30. SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
  31. while (*args && **args == '-') {
  32. int rv;
  33. /* Parse standard arguments */
  34. rv = SSL_CONF_cmd_argv(cctx, &nargs, &args);
  35. if (rv == -3) {
  36. fprintf(stderr, "Missing argument for %s\n", *args);
  37. goto err;
  38. }
  39. if (rv < 0) {
  40. fprintf(stderr, "Error in command %s\n", *args);
  41. ERR_print_errors_fp(stderr);
  42. goto err;
  43. }
  44. /* If rv > 0 we processed something so proceed to next arg */
  45. if (rv > 0)
  46. continue;
  47. /* Otherwise application specific argument processing */
  48. if (strcmp(*args, "-port") == 0) {
  49. port = args[1];
  50. if (port == NULL) {
  51. fprintf(stderr, "Missing -port argument\n");
  52. goto err;
  53. }
  54. args += 2;
  55. nargs -= 2;
  56. continue;
  57. } else {
  58. fprintf(stderr, "Unknown argument %s\n", *args);
  59. goto err;
  60. }
  61. }
  62. if (!SSL_CONF_CTX_finish(cctx)) {
  63. fprintf(stderr, "Finish error\n");
  64. ERR_print_errors_fp(stderr);
  65. goto err;
  66. }
  67. #ifdef ITERATE_CERTS
  68. /*
  69. * Demo of how to iterate over all certificates in an SSL_CTX structure.
  70. */
  71. {
  72. X509 *x;
  73. int rv;
  74. rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_FIRST);
  75. while (rv) {
  76. X509 *x = SSL_CTX_get0_certificate(ctx);
  77. X509_NAME_print_ex_fp(stdout, X509_get_subject_name(x), 0,
  78. XN_FLAG_ONELINE);
  79. printf("\n");
  80. rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_NEXT);
  81. }
  82. fflush(stdout);
  83. }
  84. #endif
  85. /* Setup server side SSL bio */
  86. ssl_bio = BIO_new_ssl(ctx, 0);
  87. if ((in = BIO_new_accept(port)) == NULL)
  88. goto err;
  89. /*
  90. * This means that when a new connection is accepted on 'in', The ssl_bio
  91. * will be 'duplicated' and have the new socket BIO push into it.
  92. * Basically it means the SSL BIO will be automatically setup
  93. */
  94. BIO_set_accept_bios(in, ssl_bio);
  95. again:
  96. /*
  97. * The first call will setup the accept socket, and the second will get a
  98. * socket. In this loop, the first actual accept will occur in the
  99. * BIO_read() function.
  100. */
  101. if (BIO_do_accept(in) <= 0)
  102. goto err;
  103. for (;;) {
  104. i = BIO_read(in, buf, 512);
  105. if (i == 0) {
  106. /*
  107. * If we have finished, remove the underlying BIO stack so the
  108. * next time we call any function for this BIO, it will attempt
  109. * to do an accept
  110. */
  111. printf("Done\n");
  112. tmp = BIO_pop(in);
  113. BIO_free_all(tmp);
  114. goto again;
  115. }
  116. if (i < 0)
  117. goto err;
  118. fwrite(buf, 1, i, stdout);
  119. fflush(stdout);
  120. }
  121. ret = 0;
  122. err:
  123. if (ret) {
  124. ERR_print_errors_fp(stderr);
  125. }
  126. BIO_free(in);
  127. exit(ret);
  128. return (!ret);
  129. }