s3_srvr.c
来自「一个用于点对点传输加密的工具包源码」· C语言 代码 · 共 1,755 行 · 第 1/3 页
C
1,755 行
SSL3_MT_CLIENT_HELLO, SSL3_RT_MAX_PLAIN_LENGTH, &ok); if (!ok) return((int)n); d=p=(unsigned char *)s->init_buf->data; /* use version from inside client hello, not from record header * (may differ: see RFC 2246, Appendix E, second paragraph) */ s->client_version=(((int)p[0])<<8)|(int)p[1]; p+=2; /* load the client random */ memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; /* get the session-id */ j= *(p++); s->hit=0; if (j == 0) { if (!ssl_get_new_session(s,1)) goto err; } else { i=ssl_get_prev_session(s,p,j); if (i == 1) { /* previous session */ s->hit=1; } else if (i == -1) goto err; else /* i == 0 */ { if (!ssl_get_new_session(s,1)) goto err; } } p+=j; n2s(p,i); if ((i == 0) && (j != 0)) { /* we need a cipher if we are not resuming a session */ al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED); goto f_err; } if ((i+p) > (d+n)) { /* not enough data */ al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH); goto f_err; } if ((i > 0) && (ssl_bytes_to_cipher_list(s,p,i,&(ciphers)) == NULL)) { goto err; } p+=i; /* If it is a hit, check that the cipher is in the list */ if ((s->hit) && (i > 0)) { j=0; id=s->session->cipher->id;#ifdef CIPHER_DEBUG printf("client sent %d ciphers\n",sk_num(ciphers));#endif for (i=0; i<sk_SSL_CIPHER_num(ciphers); i++) { c=sk_SSL_CIPHER_value(ciphers,i);#ifdef CIPHER_DEBUG printf("client [%2d of %2d]:%s\n", i,sk_num(ciphers),SSL_CIPHER_get_name(c));#endif if (c->id == id) { j=1; break; } } if (j == 0) { if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1)) { /* Very bad for multi-threading.... */ s->session->cipher=sk_SSL_CIPHER_value(ciphers, 0); } else { /* we need to have the cipher in the cipher * list if we are asked to reuse it */ al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_CIPHER_MISSING); goto f_err; } } } /* compression */ i= *(p++); q=p; for (j=0; j<i; j++) { if (p[j] == 0) break; } p+=i; if (j >= i) { /* no compress */ al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_COMPRESSION_SPECIFIED); goto f_err; } /* Worst case, we will use the NULL compression, but if we have other * options, we will now look for them. We have i-1 compression * algorithms from the client, starting at q. */ s->s3->tmp.new_compression=NULL; if (s->ctx->comp_methods != NULL) { /* See if we have a match */ int m,nn,o,v,done=0; nn=sk_SSL_COMP_num(s->ctx->comp_methods); for (m=0; m<nn; m++) { comp=sk_SSL_COMP_value(s->ctx->comp_methods,m); v=comp->id; for (o=0; o<i; o++) { if (v == q[o]) { done=1; break; } } if (done) break; } if (done) s->s3->tmp.new_compression=comp; else comp=NULL; } /* TLS does not mind if there is extra stuff */ if (s->version == SSL3_VERSION) { if (p > (d+n)) { /* wrong number of bytes, * there could be more to follow */ al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH); goto f_err; } } /* Given s->session->ciphers and ssl_get_ciphers_by_id(s), we must * pick a cipher */ if (!s->hit) { s->session->compress_meth=(comp == NULL)?0:comp->id; if (s->session->ciphers != NULL) sk_SSL_CIPHER_free(s->session->ciphers); s->session->ciphers=ciphers; if (ciphers == NULL) { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_PASSED); goto f_err; } ciphers=NULL; c=ssl3_choose_cipher(s,s->session->ciphers, ssl_get_ciphers_by_id(s)); if (c == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); goto f_err; } s->s3->tmp.new_cipher=c; } else { /* Session-id reuse */#ifdef REUSE_CIPHER_BUG STACK_OF(SSL_CIPHER) *sk; SSL_CIPHER *nc=NULL; SSL_CIPHER *ec=NULL; if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) { sk=s->session->ciphers; for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { c=sk_SSL_CIPHER_value(sk,i); if (c->algorithms & SSL_eNULL) nc=c; if (SSL_C_IS_EXPORT(c)) ec=c; } if (nc != NULL) s->s3->tmp.new_cipher=nc; else if (ec != NULL) s->s3->tmp.new_cipher=ec; else s->s3->tmp.new_cipher=s->session->cipher; } else#endif s->s3->tmp.new_cipher=s->session->cipher; } /* we now have the following setup. * client_random * cipher_list - our prefered list of ciphers * ciphers - the clients prefered list of ciphers * compression - basically ignored right now * ssl version is set - sslv3 * s->session - The ssl session has been setup. * s->hit - session reuse flag * s->tmp.new_cipher - the new cipher to use. */ ret=1; if (0) {f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); }err: if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers); return(ret); }static int ssl3_send_server_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; int i,sl; unsigned long l,Time; if (s->state == SSL3_ST_SW_SRVR_HELLO_A) { buf=(unsigned char *)s->init_buf->data; p=s->s3->server_random; Time=time(NULL); /* Time */ l2n(Time,p); RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); /* Do the message type and length last */ d=p= &(buf[4]); *(p++)=s->version>>8; *(p++)=s->version&0xff; /* Random stuff */ memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; /* now in theory we have 3 options to sending back the * session id. If it is a re-use, we send back the * old session-id, if it is a new session, we send * back the new session-id or we send back a 0 length * session-id if we want it to be single use. * Currently I will not implement the '0' length session-id * 12-Jan-98 - I'll now support the '0' length stuff. */ if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) s->session->session_id_length=0; sl=s->session->session_id_length; *(p++)=sl; memcpy(p,s->session->session_id,sl); p+=sl; /* put the cipher */ i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p); p+=i; /* put the compression method */ if (s->s3->tmp.new_compression == NULL) *(p++)=0; else *(p++)=s->s3->tmp.new_compression->id; /* do the header */ l=(p-d); d=buf; *(d++)=SSL3_MT_SERVER_HELLO; l2n3(l,d); s->state=SSL3_ST_CW_CLNT_HELLO_B; /* number of bytes to write */ s->init_num=p-buf; s->init_off=0; } /* SSL3_ST_CW_CLNT_HELLO_B */ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); }static int ssl3_send_server_done(SSL *s) { unsigned char *p; if (s->state == SSL3_ST_SW_SRVR_DONE_A) { p=(unsigned char *)s->init_buf->data; /* do the header */ *(p++)=SSL3_MT_SERVER_DONE; *(p++)=0; *(p++)=0; *(p++)=0; s->state=SSL3_ST_SW_SRVR_DONE_B; /* number of bytes to write */ s->init_num=4; s->init_off=0; } /* SSL3_ST_CW_CLNT_HELLO_B */ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); }static int ssl3_send_server_key_exchange(SSL *s) {#ifndef NO_RSA unsigned char *q; int j,num; RSA *rsa; unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; unsigned int u;#endif#ifndef NO_DH DH *dh=NULL,*dhp;#endif EVP_PKEY *pkey; unsigned char *p,*d; int al,i; unsigned long type; int n; CERT *cert; BIGNUM *r[4]; int nr[4],kn; BUF_MEM *buf; EVP_MD_CTX md_ctx; if (s->state == SSL3_ST_SW_KEY_EXCH_A) { type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK; cert=s->cert; buf=s->init_buf; r[0]=r[1]=r[2]=r[3]=NULL; n=0;#ifndef NO_RSA if (type & SSL_kRSA) { rsa=cert->rsa_tmp; if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) { rsa=s->cert->rsa_tmp_cb(s, SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); if(rsa == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY); goto f_err; } CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); cert->rsa_tmp=rsa; } if (rsa == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY); goto f_err; } r[0]=rsa->n; r[1]=rsa->e; s->s3->tmp.use_rsa_tmp=1; } else#endif#ifndef NO_DH if (type & SSL_kEDH) { dhp=cert->dh_tmp; if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) dhp=s->cert->dh_tmp_cb(s, SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); if (dhp == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); goto f_err; } if (s->s3->tmp.dh != NULL) { DH_free(dh); SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, SSL_R_INTERNAL_ERROR); goto err; } if ((dh=DHparams_dup(dhp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); goto err; } s->s3->tmp.dh=dh; if ((dhp->pub_key == NULL || dhp->priv_key == NULL || (s->options & SSL_OP_SINGLE_DH_USE))) { if(!DH_generate_key(dh)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); goto err; } } else { dh->pub_key=BN_dup(dhp->pub_key); dh->priv_key=BN_dup(dhp->priv_key); if ((dh->pub_key == NULL) || (dh->priv_key == NULL)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); goto err; } } r[0]=dh->p; r[1]=dh->g; r[2]=dh->pub_key; } else #endif { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); goto f_err; } for (i=0; r[i] != NULL; i++) { nr[i]=BN_num_bytes(r[i]); n+=2+nr[i]; } if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)) { if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) == NULL) { al=SSL_AD_DECODE_ERROR; goto f_err; } kn=EVP_PKEY_size(pkey); } else { pkey=NULL; kn=0; } if (!BUF_MEM_grow(buf,n+4+kn)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF); goto err; } d=(unsigned char *)s->init_buf->data; p= &(d[4]); for (i=0; r[i] != NULL; i++) { s2n(nr[i],p); BN_bn2bin(r[i],p); p+=nr[i]; } /* not anonymous */ if (pkey != NULL) { /* n is the length of the params, they start at &(d[4]) * and p points to the space at the end. */#ifndef NO_RSA if (pkey->type == EVP_PKEY_RSA) { q=md_buf; j=0; for (num=2; num > 0; num--) { EVP_DigestInit(&md_ctx,(num == 2) ?s->ctx->md5:s->ctx->sha1); EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(d[4]),n); EVP_DigestFinal(&md_ctx,q, (unsigned int *)&i); q+=i; j+=i; } if (RSA_sign(NID_md5_sha1, md_buf, j, &(p[2]), &u, pkey->pkey.rsa) <= 0) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA); goto err; } s2n(u,p); n+=u+2; } else#endif#if !defined(NO_DSA) if (pkey->type == EVP_PKEY_DSA) { /* lets do DSS */ EVP_SignInit(&md_ctx,EVP_dss1()); EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(d[4]),n); if (!EVP_SignFinal(&md_ctx,&(p[2]), (unsigned int *)&i,pkey)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA); goto err; } s2n(i,p); n+=i+2; } else#endif { /* Is this error check actually needed? */ al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE); goto f_err; } } *(d++)=SSL3_MT_SERVER_KEY_EXCHANGE; l2n3(n,d); /* we should now have things packed up, so lets send * it off */ s->init_num=n+4; s->init_off=0; } s->state = SSL3_ST_SW_KEY_EXCH_B; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al);err: return(-1); }static int ssl3_send_certificate_request(SSL *s) { unsigned char *p,*d; int i,j,nl,off,n; STACK_OF(X509_NAME) *sk=NULL; X509_NAME *name; BUF_MEM *buf; if (s->state == SSL3_ST_SW_CERT_REQ_A) { buf=s->init_buf; d=p=(unsigned char *)&(buf->data[4]);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?