📄 s_server.c
字号:
BIO_printf(bio_s_out,"Client certificate\n"); PEM_write_bio_X509(bio_s_out,peer); X509_NAME_oneline(X509_get_subject_name(peer),buf,sizeof buf); BIO_printf(bio_s_out,"subject=%s\n",buf); X509_NAME_oneline(X509_get_issuer_name(peer),buf,sizeof buf); BIO_printf(bio_s_out,"issuer=%s\n",buf); X509_free(peer); } if (SSL_get_shared_ciphers(con,buf,sizeof buf) != NULL) BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf); str=SSL_CIPHER_get_name(SSL_get_current_cipher(con)); BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)"); if (con->hit) BIO_printf(bio_s_out,"Reused session-id\n"); if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) & TLS1_FLAGS_TLS_PADDING_BUG) BIO_printf(bio_s_out,"Peer has incorrect TLSv1 block padding\n");#ifndef OPENSSL_NO_KRB5 if (con->kssl_ctx->client_princ != NULL) { BIO_printf(bio_s_out,"Kerberos peer principal is %s\n", con->kssl_ctx->client_princ); }#endif /* OPENSSL_NO_KRB5 */ return(1); }#ifndef OPENSSL_NO_DHstatic DH *load_dh_param(const char *dhfile) { DH *ret=NULL; BIO *bio; if ((bio=BIO_new_file(dhfile,"r")) == NULL) goto err; ret=PEM_read_bio_DHparams(bio,NULL,NULL,NULL);err: if (bio != NULL) BIO_free(bio); return(ret); }#endif#if 0static int load_CA(SSL_CTX *ctx, char *file) { FILE *in; X509 *x=NULL; if ((in=fopen(file,"r")) == NULL) return(0); for (;;) { if (PEM_read_X509(in,&x,NULL) == NULL) break; SSL_CTX_add_client_CA(ctx,x); } if (x != NULL) X509_free(x); fclose(in); return(1); }#endifstatic int www_body(char *hostname, int s, unsigned char *context) { char *buf=NULL; int ret=1; int i,j,k,blank,dot; struct stat st_buf; SSL *con; SSL_CIPHER *c; BIO *io,*ssl_bio,*sbio; long total_bytes; buf=OPENSSL_malloc(bufsize); if (buf == NULL) return(0); io=BIO_new(BIO_f_buffer()); ssl_bio=BIO_new(BIO_f_ssl()); if ((io == NULL) || (ssl_bio == NULL)) goto err;#ifdef FIONBIO if (s_nbio) { unsigned long sl=1; if (!s_quiet) BIO_printf(bio_err,"turning on non blocking io\n"); if (BIO_socket_ioctl(s,FIONBIO,&sl) < 0) ERR_print_errors(bio_err); }#endif /* lets make the output buffer a reasonable size */ if (!BIO_set_write_buffer_size(io,bufsize)) goto err; if ((con=SSL_new(ctx)) == NULL) goto err;#ifndef OPENSSL_NO_KRB5 if ((con->kssl_ctx = kssl_ctx_new()) != NULL) { kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVICE, KRB5SVC); kssl_ctx_setstring(con->kssl_ctx, KSSL_KEYTAB, KRB5KEYTAB); }#endif /* OPENSSL_NO_KRB5 */ if(context) SSL_set_session_id_context(con, context, strlen((char *)context)); sbio=BIO_new_socket(s,BIO_NOCLOSE); if (s_nbio_test) { BIO *test; test=BIO_new(BIO_f_nbio_test()); sbio=BIO_push(test,sbio); } SSL_set_bio(con,sbio,sbio); SSL_set_accept_state(con); /* SSL_set_fd(con,s); */ BIO_set_ssl(ssl_bio,con,BIO_CLOSE); BIO_push(io,ssl_bio);#ifdef CHARSET_EBCDIC io = BIO_push(BIO_new(BIO_f_ebcdic_filter()),io);#endif if (s_debug) { con->debug=1; BIO_set_callback(SSL_get_rbio(con),bio_dump_callback); BIO_set_callback_arg(SSL_get_rbio(con),bio_s_out); } if (s_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_s_out); } blank=0; for (;;) { if (hack) { i=SSL_accept(con); switch (SSL_get_error(con,i)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: continue; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: case SSL_ERROR_ZERO_RETURN: ret=1; goto err; /* break; */ } SSL_renegotiate(con); SSL_write(con,NULL,0); } i=BIO_gets(io,buf,bufsize-1); if (i < 0) /* error */ { if (!BIO_should_retry(io)) { if (!s_quiet) ERR_print_errors(bio_err); goto err; } else { BIO_printf(bio_s_out,"read R BLOCK\n");#if defined(OPENSSL_SYS_NETWARE) delay(1000);#elif !defined(OPENSSL_SYS_MSDOS) && !defined(__DJGPP__) sleep(1);#endif continue; } } else if (i == 0) /* end of input */ { ret=1; goto end; } /* else we have data */ if ( ((www == 1) && (strncmp("GET ",buf,4) == 0)) || ((www == 2) && (strncmp("GET /stats ",buf,10) == 0))) { char *p; X509 *peer; STACK_OF(SSL_CIPHER) *sk; static const char *space=" "; BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); BIO_puts(io,"<HTML><BODY BGCOLOR=\"#ffffff\">\n"); BIO_puts(io,"<pre>\n");/* BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/ BIO_puts(io,"\n"); for (i=0; i<local_argc; i++) { BIO_puts(io,local_argv[i]); BIO_write(io," ",1); } BIO_puts(io,"\n"); /* The following is evil and should not really * be done */ BIO_printf(io,"Ciphers supported in s_server binary\n"); sk=SSL_get_ciphers(con); j=sk_SSL_CIPHER_num(sk); for (i=0; i<j; i++) { c=sk_SSL_CIPHER_value(sk,i); BIO_printf(io,"%-11s:%-25s", SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); if ((((i+1)%2) == 0) && (i+1 != j)) BIO_puts(io,"\n"); } BIO_puts(io,"\n"); p=SSL_get_shared_ciphers(con,buf,bufsize); if (p != NULL) { BIO_printf(io,"---\nCiphers common between both SSL end points:\n"); j=i=0; while (*p) { if (*p == ':') { BIO_write(io,space,26-j); i++; j=0; BIO_write(io,((i%3)?" ":"\n"),1); } else { BIO_write(io,p,1); j++; } p++; } BIO_puts(io,"\n"); } BIO_printf(io,((con->hit) ?"---\nReused, " :"---\nNew, ")); c=SSL_get_current_cipher(con); BIO_printf(io,"%s, Cipher is %s\n", SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); SSL_SESSION_print(io,SSL_get_session(con)); BIO_printf(io,"---\n"); print_stats(io,SSL_get_SSL_CTX(con)); BIO_printf(io,"---\n"); peer=SSL_get_peer_certificate(con); if (peer != NULL) { BIO_printf(io,"Client certificate\n"); X509_print(io,peer); PEM_write_bio_X509(io,peer); } else BIO_puts(io,"no client certificate available\n"); BIO_puts(io,"</BODY></HTML>\r\n\r\n"); break; } else if ((www == 2 || www == 3) && (strncmp("GET /",buf,5) == 0)) { BIO *file; char *p,*e; static const char *text="HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"; /* skip the '/' */ p= &(buf[5]); dot = 1; for (e=p; *e != '\0'; e++) { if (e[0] == ' ') break; switch (dot) { case 1: dot = (e[0] == '.') ? 2 : 0; break; case 2: dot = (e[0] == '.') ? 3 : 0; break; case 3: dot = (e[0] == '/') ? -1 : 0; break; } if (dot == 0) dot = (e[0] == '/') ? 1 : 0; } dot = (dot == 3) || (dot == -1); /* filename contains ".." component */ if (*e == '\0') { BIO_puts(io,text); BIO_printf(io,"'%s' is an invalid file name\r\n",p); break; } *e='\0'; if (dot) { BIO_puts(io,text); BIO_printf(io,"'%s' contains '..' reference\r\n",p); break; } if (*p == '/') { BIO_puts(io,text); BIO_printf(io,"'%s' is an invalid path\r\n",p); break; }#if 0 /* append if a directory lookup */ if (e[-1] == '/') strcat(p,"index.html");#endif /* if a directory, do the index thang */ if (stat(p,&st_buf) < 0) { BIO_puts(io,text); BIO_printf(io,"Error accessing '%s'\r\n",p); ERR_print_errors(io); break; } if (S_ISDIR(st_buf.st_mode)) {#if 0 /* must check buffer size */ strcat(p,"/index.html");#else BIO_puts(io,text); BIO_printf(io,"'%s' is a directory\r\n",p); break;#endif } if ((file=BIO_new_file(p,"r")) == NULL) { BIO_puts(io,text); BIO_printf(io,"Error opening '%s'\r\n",p); ERR_print_errors(io); break; } if (!s_quiet) BIO_printf(bio_err,"FILE:%s\n",p); if (www == 2) { i=strlen(p); if ( ((i > 5) && (strcmp(&(p[i-5]),".html") == 0)) || ((i > 4) && (strcmp(&(p[i-4]),".php") == 0)) || ((i > 4) && (strcmp(&(p[i-4]),".htm") == 0))) BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); else BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"); } /* send the file */ total_bytes=0; for (;;) { i=BIO_read(file,buf,bufsize); if (i <= 0) break;#ifdef RENEG total_bytes+=i; fprintf(stderr,"%d\n",i); if (total_bytes > 3*1024) { total_bytes=0; fprintf(stderr,"RENEGOTIATE\n"); SSL_renegotiate(con); }#endif for (j=0; j<i; ) {#ifdef RENEG{ static count=0; if (++count == 13) { SSL_renegotiate(con); } }#endif k=BIO_write(io,&(buf[j]),i-j); if (k <= 0) { if (!BIO_should_retry(io)) goto write_error; else { BIO_printf(bio_s_out,"rwrite W BLOCK\n"); } } else { j+=k; } } }write_error: BIO_free(file); break; } } for (;;) { i=(int)BIO_flush(io); if (i <= 0) { if (!BIO_should_retry(io)) break; } else break; }end:#if 1 /* make sure we re-use sessions */ SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);#else /* This kills performance *//* SSL_shutdown(con); A shutdown gets sent in the * BIO_free_all(io) procession */#endiferr: if (ret >= 0) BIO_printf(bio_s_out,"ACCEPT\n"); if (buf != NULL) OPENSSL_free(buf); if (io != NULL) BIO_free_all(io);/* if (ssl_bio != NULL) BIO_free(ssl_bio);*/ return(ret); }#ifndef OPENSSL_NO_RSAstatic RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) { BIGNUM *bn = NULL; static RSA *rsa_tmp=NULL; if (!rsa_tmp && ((bn = BN_new()) == NULL)) BIO_printf(bio_err,"Allocation error in generating RSA key\n"); if (!rsa_tmp && bn) { if (!s_quiet) { BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength); (void)BIO_flush(bio_err); } if(!BN_set_word(bn, RSA_F4) || ((rsa_tmp = RSA_new()) == NULL) || !RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL)) { if(rsa_tmp) RSA_free(rsa_tmp); rsa_tmp = NULL; } if (!s_quiet) { BIO_printf(bio_err,"\n"); (void)BIO_flush(bio_err); } BN_free(bn); } return(rsa_tmp); }#endif#define MAX_SESSION_ID_ATTEMPTS 10static int generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len) { unsigned int count = 0; do { RAND_pseudo_bytes(id, *id_len); /* Prefix the session_id with the required prefix. NB: If our * prefix is too long, clip it - but there will be worse effects * anyway, eg. the server could only possibly create 1 session * ID (ie. the prefix!) so all future session negotiations will * fail due to conflicts. */ memcpy(id, session_id_prefix, (strlen(session_id_prefix) < *id_len) ? strlen(session_id_prefix) : *id_len); } while(SSL_has_matching_session_id(ssl, id, *id_len) && (++count < MAX_SESSION_ID_ATTEMPTS)); if(count >= MAX_SESSION_ID_ATTEMPTS) return 0; return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -