Skip to content

SPKAC functionality per feature request #38917 #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
328 changes: 328 additions & 0 deletions ext/openssl/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,11 +375,40 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_random_pseudo_bytes, 0, 0, 1)
ZEND_ARG_INFO(0, length)
ZEND_ARG_INFO(1, result_is_strong)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_spki_new, 0, 0, 2)
ZEND_ARG_INFO(0, privkey)
ZEND_ARG_INFO(0, challenge)
ZEND_ARG_INFO(0, algo)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_verify, 0)
ZEND_ARG_INFO(0, spki)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_export, 0)
ZEND_ARG_INFO(0, spki)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_export_challenge, 0)
ZEND_ARG_INFO(0, spki)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_details, 0)
ZEND_ARG_INFO(0, spki)
ZEND_END_ARG_INFO()
/* }}} */

/* {{{ openssl_functions[]
*/
const zend_function_entry openssl_functions[] = {
/* spki functions */
PHP_FE(openssl_spki_new, arginfo_openssl_spki_new)
PHP_FE(openssl_spki_verify, arginfo_openssl_spki_verify)
PHP_FE(openssl_spki_export, arginfo_openssl_spki_export)
PHP_FE(openssl_spki_export_challenge, arginfo_openssl_spki_export_challenge)
PHP_FE(openssl_spki_details, arginfo_openssl_spki_details)

/* public/private key functions */
PHP_FE(openssl_pkey_free, arginfo_openssl_pkey_free)
PHP_FE(openssl_pkey_new, arginfo_openssl_pkey_new)
Expand Down Expand Up @@ -1290,6 +1319,305 @@ PHP_FUNCTION(openssl_x509_export_to_file)
}
/* }}} */

/* {{{ proto string openssl_spki_new(mixed zpkey, string challenge [, string algo='sha256'])
Creates new private key (or uses existing) and creates a new spki cert
outputting results to var */
PHP_FUNCTION(openssl_spki_new)
{
int challenge_len, algo_len;
char * challenge, * spkstr, * algo="sha256", * s;
long keyresource = -1;
const char *spkac = "SPKAC=";

zval * zpkey = NULL;
EVP_PKEY * pkey = NULL;
NETSCAPE_SPKI *spki=NULL;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|s", &zpkey, &challenge, &challenge_len, &algo, &algo_len) == FAILURE) {
return;
}

pkey = php_openssl_evp_from_zval(&zpkey, 0, challenge, 1, &keyresource TSRMLS_CC);

if (pkey == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to use supplied private key");
RETURN_NULL();
}

if ((spki = NETSCAPE_SPKI_new()) == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to create new SPKAC");
RETURN_NULL();
}

if (challenge) {
ASN1_STRING_set(spki->spkac->challenge, challenge, (int)strlen(challenge));
}

if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to embed public key");
RETURN_NULL();
}

if (strcmp(algo, "md5")==0){
if (!NETSCAPE_SPKI_sign(spki, pkey, EVP_md5())) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to sign with md5 algorithm");
RETURN_NULL();
}
} else if(strcmp(algo, "sha1")==0){
if (!NETSCAPE_SPKI_sign(spki, pkey, EVP_sha1())) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to sign with sha1 algorithm");
RETURN_NULL();
}
} else if(strcmp(algo, "sha256")==0){
if (!NETSCAPE_SPKI_sign(spki, pkey, EVP_sha256())) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to sign with sha256 algorithm");
RETURN_NULL();
}
} else if (strcmp(algo, "sha512")==0){
if (!NETSCAPE_SPKI_sign(spki, pkey, EVP_sha512())) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to sign with sha512 algorithm");
RETURN_NULL();
}
}

spkstr = NETSCAPE_SPKI_b64_encode(spki);
if (!spkstr){
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable encode SPKAC");
RETURN_NULL();
}

s = emalloc(strlen(spkac) + strlen(spkstr) + 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this one definitely leaked on errors, and probably also leaked on normal return.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi:

On Tue, Apr 3, 2012 at 3:39 PM, Stanislav Malyshev
[email protected]
wrote:

  •            RETURN_NULL();
  •        }
  •    } else if (strcmp(algo, "sha512")==0){
  •        if (!NETSCAPE_SPKI_sign(spki, pkey, EVP_sha512())) {
  •            php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to sign with sha512 algorithm");

should we make an RFC, that the error message should be in ucfirst
form, or lower case ?

I see there are both ucfirst warnig message and lowercase messages
in php-src.

thanks

  •            RETURN_NULL();
  •        }
  •    }
    +
  •    spkstr = NETSCAPE_SPKI_b64_encode(spki);
  •    if (!spkstr){
  •        php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable encode SPKAC");
  •        RETURN_NULL();
  •    }
    +
  •    s = emalloc(strlen(spkac) + strlen(spkstr) + 1);

Looks like this one definitely leaked on errors, and probably also leaked on normal return.


Reply to this email directly or view it on GitHub:
https://github.com/php/php-src/pull/21/files#r637678

Git Pull Requests Mailing List (https://github.com/php)
To unsubscribe, visit: http://www.php.net/unsub.php

Laruence  Xinchen Hui
http://www.laruence.com/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used all lc due to additional functions in etc/openssl/openssl.c using all lc for warnings

sprintf(s, "%s%s", spkac, spkstr);

if (sizeof(s)<=0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate memory for SPKAC");
RETURN_NULL();
}

if (keyresource == -1 && spki != NULL) {
NETSCAPE_SPKI_free(spki);
}
if (keyresource == -1 && pkey != NULL) {
EVP_PKEY_free(pkey);
}

RETURN_STRINGL(s, strlen(s), 1);
}
/* }}} */

/* {{{ proto bool openssl_spki_verify(string spki)
Verifies spki returns boolean */
PHP_FUNCTION(openssl_spki_verify)
{
int spkstr_len, i;
char *spkstr = NULL, * spkstr_cleaned;

EVP_PKEY *pkey = NULL;
NETSCAPE_SPKI *spki = NULL;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) {
return;
}

if (spkstr == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to use supplied SPKAC");
RETURN_FALSE;
}

spkstr_cleaned = emalloc(spkstr_len + 1);
openssl_spki_cleanup(spkstr, spkstr_cleaned);

if (strlen(spkstr_cleaned)<=0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate memory for SPKAC");
RETURN_FALSE;
}

spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, strlen(spkstr_cleaned));
if (spki == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to decode supplied SPKAC");
RETURN_FALSE;
}

pkey = X509_PUBKEY_get(spki->spkac->pubkey);
if (pkey == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to aquire signed public key");
RETURN_FALSE;
}

i = NETSCAPE_SPKI_verify(spki, pkey);

if (spki != NULL) {
NETSCAPE_SPKI_free(spki);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}

if (i > 0) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
/* }}} */

/* {{{ proto string openssl_spki_export(string spki)
Exports public key from existing spki to var */
PHP_FUNCTION(openssl_spki_export)
{
int spkstr_len;
char *spkstr, * spkstr_cleaned, * s;

EVP_PKEY *pkey = NULL;
NETSCAPE_SPKI *spki = NULL;
BIO *out = BIO_new(BIO_s_mem());
BUF_MEM *bio_buf;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) {
return;
}

if (spkstr == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to use supplied SPKAC");
RETURN_NULL();
}

spkstr_cleaned = emalloc(spkstr_len + 1);
openssl_spki_cleanup(spkstr, spkstr_cleaned);

spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, strlen(spkstr_cleaned));
if (spki == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to decode supplied SPKAC");
RETURN_NULL();
}

pkey = X509_PUBKEY_get(spki->spkac->pubkey);
if (pkey == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to aquire signed public key");
RETURN_NULL();
}

PEM_write_bio_PUBKEY(out, pkey);
BIO_get_mem_ptr(out, &bio_buf);

if ((!bio_buf->data)&&(bio_buf->length<=0)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate memory for public key");
RETURN_NULL();
}

s = emalloc(bio_buf->length);
BIO_read(out, s, bio_buf->length);

if (spki != NULL) {
NETSCAPE_SPKI_free(spki);
}
if (out != NULL) {
BIO_free_all(out);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}

RETURN_STRINGL(s, strlen(s), 1);
}
/* }}} */

/* {{{ proto string openssl_spki_export_challenge(string spki)
Exports spkac challenge from existing spki to var */
PHP_FUNCTION(openssl_spki_export_challenge)
{
int spkstr_len;
char *spkstr, * spkstr_cleaned;

NETSCAPE_SPKI *spki = NULL;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) {
return;
}

if (spkstr == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to use supplied SPKAC");
RETURN_NULL();
}

spkstr_cleaned = emalloc(spkstr_len + 1);
openssl_spki_cleanup(spkstr, spkstr_cleaned);

spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, strlen(spkstr_cleaned));
if (spki == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate memory for public key");
RETURN_NULL();
}

RETURN_STRINGL(ASN1_STRING_data(spki->spkac->challenge), strlen(ASN1_STRING_data(spki->spkac->challenge)), 1);
}
/* }}} */

/* {{{ proto string openssl_spki_details(string spki)
Provides details from existing spki to var */
PHP_FUNCTION(openssl_spki_details)
{
int spkstr_len;
char *spkstr, * spkstr_cleaned, * s;

NETSCAPE_SPKI *spki = NULL;
BIO *out = BIO_new(BIO_s_mem());
BUF_MEM *bio_buf;
zval *zout;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &spkstr, &spkstr_len) == FAILURE) {
return;
}

if (!spkstr) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to use supplied SPKAC");
RETURN_NULL();
}

spkstr_cleaned = emalloc(spkstr_len + 1);
openssl_spki_cleanup(spkstr, spkstr_cleaned);

spki = NETSCAPE_SPKI_b64_decode(spkstr_cleaned, strlen(spkstr_cleaned));
if (!spki) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to decode supplied SPKAC");
RETURN_NULL();
}

NETSCAPE_SPKI_print(out, spki);
BIO_get_mem_ptr(out, &bio_buf);

if ((!bio_buf->data)&&(bio_buf->length<=0)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to obtain details of SPKAC");
RETURN_NULL();
}

s = malloc(bio_buf->length);
BIO_read(out, s, bio_buf->length);

RETURN_STRINGL(s, strlen(s), 1);
}
/* }}} */

/* {{{ proto int openssl_spki_cleanup(const char *src, char *results)
This will help remove new line chars in the SPKAC sent from the
browser */
int openssl_spki_cleanup(const char *src, char *dest)
{
int removed=0;

while (*src) {
if (*src!='\n'&&*src!='\r') {
*dest++=*src;
} else {
++removed;
}
++src;
}
*dest=0;
return removed;
}
/* }}} */

/* {{{ proto bool openssl_x509_export(mixed x509, string &out [, bool notext = true])
Exports a CERT to file or a var */
PHP_FUNCTION(openssl_x509_export)
Expand Down
6 changes: 6 additions & 0 deletions ext/openssl/php_openssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ PHP_FUNCTION(openssl_csr_export_to_file);
PHP_FUNCTION(openssl_csr_sign);
PHP_FUNCTION(openssl_csr_get_subject);
PHP_FUNCTION(openssl_csr_get_public_key);

PHP_FUNCTION(openssl_spki_new);
PHP_FUNCTION(openssl_spki_verify);
PHP_FUNCTION(openssl_spki_export);
PHP_FUNCTION(openssl_spki_export_challenge);
PHP_FUNCTION(openssl_spki_details);
#else

#define phpext_openssl_ptr NULL
Expand Down
Loading