📄 openssl.c
字号:
if (NULL == pkey->pkey.dh->p || NULL == pkey->pkey.dh->priv_key) return 0; break;#endif default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!"); break; } return 1;}/* }}} *//* {{{ proto resource openssl_pkey_new([array configargs]) Generates a new private key */PHP_FUNCTION(openssl_pkey_new){ struct php_x509_request req; zval * args = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &args) == FAILURE) return; RETVAL_FALSE; PHP_SSL_REQ_INIT(&req); if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) { if (php_openssl_generate_private_key(&req TSRMLS_CC)) { /* pass back a key resource */ RETVAL_RESOURCE(zend_list_insert(req.priv_key, le_key)); /* make sure the cleanup code doesn't zap it! */ req.priv_key = NULL; } } PHP_SSL_REQ_DISPOSE(&req);}/* }}} *//* {{{ proto bool openssl_pkey_export_to_file(mixed key, string outfilename [, string passphrase, array config_args) Gets an exportable representation of a key into a file */PHP_FUNCTION(openssl_pkey_export_to_file){ struct php_x509_request req; zval * zpkey, * args = NULL; char * passphrase = NULL; int passphrase_len = 0; char * filename = NULL; int filename_len = 0; long key_resource = -1; EVP_PKEY * key; BIO * bio_out = NULL; EVP_CIPHER * cipher; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) return; RETVAL_FALSE; key = php_openssl_evp_from_zval(&zpkey, 0, passphrase, 0, &key_resource TSRMLS_CC); if (key == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get key from parameter 1"); RETURN_FALSE; } if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { RETURN_FALSE; } PHP_SSL_REQ_INIT(&req); if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) { bio_out = BIO_new_file(filename, "w"); if (passphrase && req.priv_key_encrypt) cipher = (EVP_CIPHER *) EVP_des_ede3_cbc(); else cipher = NULL; if (PEM_write_bio_PrivateKey(bio_out, key, cipher, passphrase, passphrase_len, NULL, NULL)) { /* Success! * If returning the output as a string, do so now */ RETVAL_TRUE; } } PHP_SSL_REQ_DISPOSE(&req); if (key_resource == -1 && key) { EVP_PKEY_free(key); } if (bio_out) BIO_free(bio_out);}/* }}} *//* {{{ proto bool openssl_pkey_export(mixed key, &mixed out [, string passphrase [, array config_args]]) Gets an exportable representation of a key into a string or file */PHP_FUNCTION(openssl_pkey_export){ struct php_x509_request req; zval * zpkey, * args = NULL, *out; char * passphrase = NULL; int passphrase_len = 0; long key_resource = -1; EVP_PKEY * key; BIO * bio_out = NULL; EVP_CIPHER * cipher; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) return; RETVAL_FALSE; key = php_openssl_evp_from_zval(&zpkey, 0, passphrase, 0, &key_resource TSRMLS_CC); if (key == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get key from parameter 1"); RETURN_FALSE; } PHP_SSL_REQ_INIT(&req); if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) { bio_out = BIO_new(BIO_s_mem()); if (passphrase && req.priv_key_encrypt) cipher = (EVP_CIPHER *) EVP_des_ede3_cbc(); else cipher = NULL; if (PEM_write_bio_PrivateKey(bio_out, key, cipher, passphrase, passphrase_len, NULL, NULL)) { /* Success! * If returning the output as a string, do so now */ char * bio_mem_ptr; long bio_mem_len; RETVAL_TRUE; bio_mem_len = BIO_get_mem_data(bio_out, &bio_mem_ptr); ZVAL_STRINGL(out, bio_mem_ptr, bio_mem_len, 1); } } PHP_SSL_REQ_DISPOSE(&req); if (key_resource == -1 && key) { EVP_PKEY_free(key); } if (bio_out) BIO_free(bio_out);}/* }}} *//* {{{ proto int openssl_pkey_get_public(mixed cert) Gets public key from X.509 certificate */PHP_FUNCTION(openssl_pkey_get_public){ zval *cert; EVP_PKEY *pkey; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &cert) == FAILURE) return; Z_TYPE_P(return_value) = IS_RESOURCE; pkey = php_openssl_evp_from_zval(&cert, 1, NULL, 1, &Z_LVAL_P(return_value) TSRMLS_CC); if (pkey == NULL) { RETURN_FALSE; }}/* }}} *//* {{{ proto void openssl_pkey_free(int key) Frees a key */PHP_FUNCTION(openssl_pkey_free){ zval *key; EVP_PKEY *pkey; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &key) == FAILURE) return; ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, &key, -1, "OpenSSL key", le_key); zend_list_delete(Z_LVAL_P(key));}/* }}} *//* {{{ proto int openssl_pkey_get_private(string key [, string passphrase]) Gets private keys */PHP_FUNCTION(openssl_pkey_get_private){ zval *cert; EVP_PKEY *pkey; char * passphrase = ""; int passphrase_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &cert, &passphrase, &passphrase_len) == FAILURE) return; Z_TYPE_P(return_value) = IS_RESOURCE; pkey = php_openssl_evp_from_zval(&cert, 0, passphrase, 1, &Z_LVAL_P(return_value) TSRMLS_CC); if (pkey == NULL) { RETURN_FALSE; }}/* }}} *//* }}} *//* {{{ PKCS7 S/MIME functions *//* {{{ proto bool openssl_pkcs7_verify(string filename, long flags [, string signerscerts [, array cainfo [, string extracerts]]]) Verifys that the data block is intact, the signer is who they say they are, and returns the CERTs of the signers */PHP_FUNCTION(openssl_pkcs7_verify){ X509_STORE * store = NULL; zval * cainfo = NULL; STACK_OF(X509) *signers= NULL; STACK_OF(X509) *others = NULL; PKCS7 * p7 = NULL; BIO * in = NULL, * datain = NULL; long flags = 0; char * filename; int filename_len; char * extracerts = NULL; int extracerts_len; char * signersfilename = NULL; int signersfilename_len; RETVAL_LONG(-1); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|sas", &filename, &filename_len, &flags, &signersfilename, &signersfilename_len, &cainfo, &extracerts, &extracerts_len) == FAILURE) return; if (extracerts) { others = load_all_certs_from_file(extracerts); if (others == NULL) goto clean_exit; } flags = flags & ~PKCS7_DETACHED; store = setup_verify(cainfo TSRMLS_CC); if (!store) goto clean_exit; if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { goto clean_exit; } in = BIO_new_file(filename, (flags & PKCS7_BINARY) ? "rb" : "r"); if (in == NULL) goto clean_exit; p7 = SMIME_read_PKCS7(in, &datain); if (p7 == NULL) {#if DEBUG_SMIME zend_printf("SMIME_read_PKCS7 failed\n");#endif goto clean_exit; }#if DEBUG_SMIME zend_printf("Calling PKCS7 verify\n");#endif if (PKCS7_verify(p7, others, store, datain, NULL, flags)) { RETVAL_TRUE; if (signersfilename) { BIO *certout; if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { goto clean_exit; } certout = BIO_new_file(signersfilename, "w"); if (certout) { int i; signers = PKCS7_get0_signers(p7, NULL, flags); for(i = 0; i < sk_X509_num(signers); i++) PEM_write_bio_X509(certout, sk_X509_value(signers, i)); BIO_free(certout); sk_X509_free(signers); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "signature OK, but cannot open %s for writing", signersfilename); RETVAL_LONG(-1); } } goto clean_exit; } else RETVAL_FALSE;clean_exit: X509_STORE_free(store); BIO_free(datain); BIO_free(in); PKCS7_free(p7); sk_X509_free(others);}/* }}} *//* {{{ proto bool openssl_pkcs7_encrypt(string infile, string outfile, mixed recipcerts, array headers [, long flags]) Encrypts the message in the file named infile with the certificates in recipcerts and output the result to the file named outfile */PHP_FUNCTION(openssl_pkcs7_encrypt){ zval * zrecipcerts, * zheaders = NULL; STACK_OF(X509) * recipcerts = NULL; BIO * infile = NULL, * outfile = NULL; long flags = 0; PKCS7 * p7 = NULL; HashPosition hpos; zval ** zcertval; X509 * cert; EVP_CIPHER *cipher = NULL; uint strindexlen; ulong intindex; char * strindex; char * infilename = NULL; int infilename_len; char * outfilename = NULL; int outfilename_len; RETVAL_FALSE; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssza!|l", &infilename, &infilename_len, &outfilename, &outfilename_len, &zrecipcerts, &zheaders, &flags) == FAILURE) return; if (php_openssl_safe_mode_chk(infilename TSRMLS_CC) || php_openssl_safe_mode_chk(outfilename TSRMLS_CC)) { return; } infile = BIO_new_file(infilename, "r"); if (infile == NULL) goto clean_exit; outfile = BIO_new_file(outfilename, "w"); if (outfile == NULL) goto clean_exit; recipcerts = sk_X509_new_null(); /* get certs */ if (Z_TYPE_P(zrecipcerts) == IS_ARRAY) { zend_hash_internal_pointer_reset_ex(HASH_OF(zrecipcerts), &hpos); while(zend_hash_get_current_data_ex(HASH_OF(zrecipcerts), (void**)&zcertval, &hpos) == SUCCESS) { long certresource; cert = php_openssl_x509_from_zval(zcertval, 0, &certresource TSRMLS_CC); if (cert == NULL) goto clean_exit; if (certresource != -1) { /* we shouldn't free this particular cert, as it is a resource. make a copy and push that on the stack instead */ cert = X509_dup(cert); if (cert == NULL) goto clean_exit; } sk_X509_push(recipcerts, cert); zend_hash_move_forward_ex(HASH_OF(zrecipcerts), &hpos); } } else { /* a single certificate */ long certresource; cert = php_openssl_x509_from_zval(&zrecipcerts, 0, &certresource TSRMLS_CC); if (cert == NULL) goto clean_exit; if (certresource != -1) { /* we shouldn't free this particular cert, as it is a resource. make a copy and push that on the stack instead */ cert = X509_dup(cert); if (cert == NULL) goto clean_exit; } sk_X509_push(recipcerts, cert); } /* TODO: allow user to choose a different cipher */ cipher = (EVP_CIPHER *) EVP_rc2_40_cbc(); if (cipher == NULL) goto clean_exit; p7 = PKCS7_encrypt(recipcerts, infile, cipher, flags); if (p7 == NULL) goto clean_exit; /* tack on extra headers */ if (zheaders) { zend_hash_internal_pointer_reset_ex(HASH_OF(zheaders), &hpos); while(zend_hash_get_current_data_ex(HASH_OF(zheaders), (void**)&zcertval, &hpos) == SUCCESS) { zend_hash_get_current_key_ex(HASH_OF(zheaders), &strindex, &strindexlen, &intindex, 0, &hpos); convert_to_string_ex(zcertval); if (strindex) BIO_printf(outfile, "%s: %s\n", strindex, Z_STRVAL_PP(zcertval)); else BIO_printf(outfile, "%s\n", Z_STRVAL_PP(zcertval)); zend_hash_move_forward_ex(HASH_OF(zheaders), &hpos); } } BIO_reset(infile); /* write the encrypted data */ SMIME_write_PKCS7(outfile, p7, infile, flags); RETVAL_TRUE;clean_exit: PKCS7_free(p7); BIO_free(infile); BIO_free(outfile); if (recipcerts) sk_X509_pop_free(recipcerts, X509_free);}/* }}} *//* {{{ proto bool openssl_pkcs7_sign(string infile, string outfile, mixed signcert, mixed signkey, array headers [, long flags [, string extracertsfilename]]) Signs the MIME message in the file named infile with signcert/signkey and output the result to file name outfile. headers lists plain text headers to exclude from the signed portion of the message, and should include to, from and subject as a minimum */PHP_FUNCTION(openssl_pkcs7_sign){ zval * zcert, * zprivkey, * zheaders; zval ** hval; X509 * cert = NULL; EVP_PKEY * privkey = NULL; long flags = PKCS7_DETACHED; PKCS7 * p7 = NULL; BIO * infile = NULL, * outfile = NULL; STACK_OF(X509) *others = NULL; long certresource = -1, keyresource = -1; ulong intindex; uint strindexlen; HashPosition hpos; char * strindex; char * infilename; int infilename_len; char * outfilename; int outfilename_len; char * extracertsfilename = NULL; int extracertsfilename_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sszza!|ls", &infilename, &infilename_len, &outfilename, &outfilename_len, &zcert, &zprivkey, &zheaders, &flags, &extracertsfilename, &extracertsfilename_len) == FAILURE) return; RETVAL_FALSE; if (extracertsfilename) { others = load_all_certs_from_file(extracertsfilename); if (others == NULL) goto clean_exit; } privkey = php_openssl_evp_from_zval(&zprivkey, 0, "", 0, &keyresource TSRMLS_CC); if (privkey == NULL) { php_error_docref(NULL TSR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -