Crypt-MatrixSSL

 view release on metacpan or  search on metacpan

MatrixSSL.pm  view on Meta::CPAN

    SSL_ALERT_ILLEGAL_PARAMETER
);

# for debug
our %mxSSL_RETURN_CODES = (
    0+constant('SSL_SUCCESS')       => 'SSL_SUCCESS	Generic success',
    0+constant('SSL_ERROR')         => 'SSL_ERROR	generic ssl error, see error code',
    0+constant('SSL_FULL')          => 'SSL_FULL	must call sslRead before decoding',
    0+constant('SSL_PARTIAL')       => 'SSL_PARTIAL	more data reqired to parse full msg',
    0+constant('SSL_SEND_RESPONSE') => 'SSL_SEND_RESPONSE	decode produced output data',
    0+constant('SSL_PROCESS_DATA')  => 'SSL_PROCESS_DATA	succesfully decoded application data',
    0+constant('SSL_ALERT')         => 'SSL_ALERT	weve decoded an alert',
    0+constant('SSL_FILE_NOT_FOUND')=> 'SSL_FILE_NOT_FOUND	File not found',
    0+constant('SSL_MEM_ERROR')     => 'SSL_MEM_ERROR	Memory allocation failure',
);


1;
__END__
# Below is stub documentation for your module. You'd better edit it!

=head1 NAME

MatrixSSL.pm  view on Meta::CPAN



=head1 FUNCTIONS

=over

=item B<matrixSslDecode>( $ssl, $inBuf, $outBuf, $error, $alertLevel, $alertDescription )

$inBuf and $outBuf are usual string scalars, not (sslBuf_t *) as in C interface.

After succesfull decoding one packet, matrixSslDecode() will cut decoded
packet from $inBuf's beginning.

Reply SSL packets or application data will be appended to $outBuf, if any.

To convert error/alert codes into text use exported hashes:

 $SSL_alertDescription{ $error }
 $SSL_alertLevel{ $alertLevel }
 $SSL_alertDescription{ $alertDescription }

matrixSsl.h  view on Meta::CPAN


/*
	Return codes from public apis
	Not all apis return all codes.  See documentation for more details.
*/
#define		SSL_SUCCESS			0	/* Generic success */
#define		SSL_ERROR			-1	/* generic ssl error, see error code */
#define		SSL_FULL			-2	/* must call sslRead before decoding */
#define		SSL_PARTIAL			-3	/* more data reqired to parse full msg */
#define		SSL_SEND_RESPONSE	-4	/* decode produced output data */
#define		SSL_PROCESS_DATA	-5	/* succesfully decoded application data */
#define		SSL_ALERT			-6	/* we've decoded an alert */
#define		SSL_FILE_NOT_FOUND	-7	/* File not found */
#define		SSL_MEM_ERROR		-8	/* Memory allocation failure */

/*
	SSL Alert levels and descriptions
	This implementation treats all alerts as fatal
*/
#define SSL_ALERT_LEVEL_WARNING				1
#define SSL_ALERT_LEVEL_FATAL				2

matrixssl-1-8-6-open/examples/httpsReflector.c  view on Meta::CPAN

*/
		if (memcmp(buf, againString,
				min(c - buf, (int)strlen(againString))) == 0) {
			again++;
			fprintf(stdout, "A");
		} else {
			fprintf(stdout, "R");
			again = 0;
		}
/*
		Copy the canned response header and decoded data from socket as the
		response (reflector)
*/
		responseHdrLen = (int)strlen(responseHdr);
		bytes = responseHdrLen + (int)(c - buf);
		response = malloc(bytes);
		memcpy(response, responseHdr, responseHdrLen);
		memcpy(response + responseHdrLen, buf, c - buf); 
/*
		Send response.
		< 0 return indicates an error.

matrixssl-1-8-6-open/examples/sslSocket.c  view on Meta::CPAN

{
	int				bytes, rc, remaining;
	unsigned char	error, alertLevel, alertDescription, performRead;

	*status = 0;

	if (cp->ssl == NULL || len <= 0) {
		return -1;
	}
/*
	If inbuf is valid, then we have previously decoded data that must be
	returned, return as much as possible.  Once all buffered data is
	returned, free the inbuf.
*/
	if (cp->inbuf.buf) {
		if (cp->inbuf.start < cp->inbuf.end) {
			remaining = (int)(cp->inbuf.end - cp->inbuf.start);
			bytes = (int)min(len, remaining);
			memcpy(buf, cp->inbuf.start, bytes);
			cp->inbuf.start += bytes;
			return bytes;

matrixssl-1-8-6-open/examples/sslSocket.c  view on Meta::CPAN

*/
decodeMore:
	error = 0;
	alertLevel = 0;
	alertDescription = 0;

	rc = matrixSslDecode(cp->ssl, &cp->insock, &cp->inbuf, &error, &alertLevel, 
		&alertDescription);
	switch (rc) {
/*
	Successfully decoded a record that did not return data or require a response.
*/
	case SSL_SUCCESS:
		return 0;
/*
	Successfully decoded an application data record, and placed in tmp buf
*/
	case SSL_PROCESS_DATA:
/*
		Copy as much as we can from the temp buffer into the caller's buffer
		and leave the remainder in conn->inbuf until the next call to read
		It is possible that len > data in buffer if the encoded record
		was longer than len, but the decoded record isn't!
*/
		rc = (int)(cp->inbuf.end - cp->inbuf.start);
		rc = min(rc, len);
		memcpy(buf, cp->inbuf.start, rc);
		cp->inbuf.start += rc;
		return rc;
/*
	We've decoded a record that requires a response into tmp
	If there is no data to be flushed in the out buffer, we can write out
	the contents of the tmp buffer.  Otherwise, we need to append the data 
	to the outgoing data buffer and flush it out.
*/
	case SSL_SEND_RESPONSE:
		bytes = send(cp->fd, (char *)cp->inbuf.start, 
			(int)(cp->inbuf.end - cp->inbuf.start), MSG_NOSIGNAL);
		if (bytes == SOCKET_ERROR) {
			*status = getSocketError();
			if (*status != WOULD_BLOCK) {

matrixssl-1-8-6-open/examples/sslSocket.c  view on Meta::CPAN

*/
	case SSL_ERROR:
		fprintf(stderr, "SSL: Closing on protocol error %d\n", error);
		if (cp->inbuf.start < cp->inbuf.end) {
			setSocketNonblock(cp->fd);
			bytes = send(cp->fd, (char *)cp->inbuf.start, 
				(int)(cp->inbuf.end - cp->inbuf.start), MSG_NOSIGNAL);
		}
		goto readError;
/*
	We've decoded an alert.  The level and description passed into
	matrixSslDecode are filled in with the specifics.
*/
	case SSL_ALERT:
		if (alertDescription == SSL_ALERT_CLOSE_NOTIFY) {
			*status = SSLSOCKET_CLOSE_NOTIFY;
			goto readZero;
		}
		fprintf(stderr, "SSL: Closing on client alert %d: %d\n",
			alertLevel, alertDescription);
		goto readError;

matrixssl-1-8-6-open/examples/sslSocket.c  view on Meta::CPAN

		}
		if (!performRead) {
			performRead = 1;
			free(cp->inbuf.buf);
			cp->inbuf.buf = NULL;
			goto readMore;
		} else {
			goto readZero;
		}
/*
	The out buffer is too small to fit the decoded or response
	data.  Increase the size of the buffer and call decode again
*/
	case SSL_FULL:
		cp->inbuf.size *= 2;
		if (cp->inbuf.buf != (unsigned char*)buf) {
			free(cp->inbuf.buf);
			cp->inbuf.buf = NULL;
		}
		cp->inbuf.start = cp->inbuf.end = cp->inbuf.buf = 
			(unsigned char *)malloc(cp->inbuf.size);

matrixssl-1-8-6-open/matrixSsl.h  view on Meta::CPAN


/*
	Return codes from public apis
	Not all apis return all codes.  See documentation for more details.
*/
#define		SSL_SUCCESS			0	/* Generic success */
#define		SSL_ERROR			-1	/* generic ssl error, see error code */
#define		SSL_FULL			-2	/* must call sslRead before decoding */
#define		SSL_PARTIAL			-3	/* more data reqired to parse full msg */
#define		SSL_SEND_RESPONSE	-4	/* decode produced output data */
#define		SSL_PROCESS_DATA	-5	/* succesfully decoded application data */
#define		SSL_ALERT			-6	/* we've decoded an alert */
#define		SSL_FILE_NOT_FOUND	-7	/* File not found */
#define		SSL_MEM_ERROR		-8	/* Memory allocation failure */

/*
	SSL Alert levels and descriptions
	This implementation treats all alerts as fatal
*/
#define SSL_ALERT_LEVEL_WARNING				1
#define SSL_ALERT_LEVEL_FATAL				2

matrixssl-1-8-6-open/src/sslDecode.c  view on Meta::CPAN

	before we parse it.  This is because we need to MAC the entire record before
	allowing it to be used by the caller.  The only alternative would be to 
	copy the partial record to an internal buffer, but that would require more
	memory usage, which we're trying to keep low.
*/
	if (end - c < ssl->rec.len) {
		return SSL_PARTIAL;
	}

/*
	Make sure we have enough room to hold the decoded record
*/
	if ((out->buf + out->size) - out->end < ssl->rec.len) {
		return SSL_FULL;
	}

/*
	Decrypt the entire record contents.  The record length should be
	a multiple of block size, or decrypt will return an error
	If we're still handshaking and sending plaintext, the decryption 
	callback will point to a null provider that passes the data unchanged

matrixssl-1-8-6-open/src/sslDecode.c  view on Meta::CPAN

	}
/*
	Should not get here
*/
	matrixIntDebugMsg("Invalid record type in matrixSslDecode: %d\n",
		ssl->rec.type);
	return SSL_ERROR;

encodeResponse:
/*
	We decoded a record that needs a response, either a handshake response
	or an alert if we've detected an error.  

	SECURITY - Clear the decoded incoming record from outbuf before encoding
	the response into outbuf.  rec.len could be invalid, clear the minimum 
	of rec.len and remaining outbuf size
*/
	rc = min (ssl->rec.len, (int32)((out->buf + out->size) - out->end));
	if (rc > 0) {
		memset(out->end, 0x0, rc);
	}
	if (ssl->hsState == SSL_HS_HELLO_REQUEST) {
/*
		Don't clear the session info.  If receiving a HELLO_REQUEST from a 

matrixssl-1-8-6-open/src/sslEncode.c  view on Meta::CPAN

			3 byte length of certificate + 3
			3 byte length of certificate
			certificate data
		For more than one certificate:
			3 byte length of all certificate data
			3 byte length of first certificate
			first certificate data
			3 byte length of second certificate
			second certificate data
	Certificate data is the base64 section of an X.509 certificate file
	in PEM format decoded to binary.  No additional interpretation is required.
*/
static int32 writeCertificate(ssl_t *ssl, sslBuf_t *out, int32 notEmpty)
{
	sslLocalCert_t	*cert;
	unsigned char	*c, *end, *encryptStart;
	char			padLen;
	int32			totalCertLen, certLen, lsize, messageSize, i, rc;


	c = out->end;

ppmblib/lib/Crypt/MatrixSSL.pm  view on Meta::CPAN

    SSL_ALERT_ILLEGAL_PARAMETER
);

# for debug
our %mxSSL_RETURN_CODES = (
    0+constant('SSL_SUCCESS')       => 'SSL_SUCCESS	Generic success',
    0+constant('SSL_ERROR')         => 'SSL_ERROR	generic ssl error, see error code',
    0+constant('SSL_FULL')          => 'SSL_FULL	must call sslRead before decoding',
    0+constant('SSL_PARTIAL')       => 'SSL_PARTIAL	more data reqired to parse full msg',
    0+constant('SSL_SEND_RESPONSE') => 'SSL_SEND_RESPONSE	decode produced output data',
    0+constant('SSL_PROCESS_DATA')  => 'SSL_PROCESS_DATA	succesfully decoded application data',
    0+constant('SSL_ALERT')         => 'SSL_ALERT	weve decoded an alert',
    0+constant('SSL_FILE_NOT_FOUND')=> 'SSL_FILE_NOT_FOUND	File not found',
    0+constant('SSL_MEM_ERROR')     => 'SSL_MEM_ERROR	Memory allocation failure',
);


1;
__END__
# Below is stub documentation for your module. You'd better edit it!

=head1 NAME

ppmblib/lib/Crypt/MatrixSSL.pm  view on Meta::CPAN



=head1 FUNCTIONS

=over

=item B<matrixSslDecode>( $ssl, $inBuf, $outBuf, $error, $alertLevel, $alertDescription )

$inBuf and $outBuf are usual string scalars, not (sslBuf_t *) as in C interface.

After succesfull decoding one packet, matrixSslDecode() will cut decoded
packet from $inBuf's beginning.

Reply SSL packets or application data will be appended to $outBuf, if any.

To convert error/alert codes into text use exported hashes:

 $SSL_alertDescription{ $error }
 $SSL_alertLevel{ $alertLevel }
 $SSL_alertDescription{ $alertDescription }

ppmblib/lib/Crypt/sample_functions.pl  view on Meta::CPAN

            my $s = substr($appOut, 0, $SSL_MAX_PLAINTEXT_LEN, q{});
            matrixSslEncode($ssl, $s, $out)
                >= 0 or die 'matrixSslEncode';
        }
    }
    @_[1 .. $#_] = ($in, $out, $appIn, $appOut, $handshakeIsComplete);
    return $err;
}

# Wrapper for matrixSslDecode() to separate two kind of output buffers -
# SSL packets which should be sent to other side and decoded application data:
#   $out param will contain SSL packets.
#   $data param will contain decoded application data.
# TODO  Realize this in XS?
sub matrixSslDecode2 {
    my ($ssl, $in, $out, $data, $error, $alertLevel, $alertDescription) = @_;
    my $rc = matrixSslDecode($ssl, $in, my $tmp=q{},
        $error, $alertLevel, $alertDescription);
    ($rc == $SSL_PROCESS_DATA ? $data : $out) .= $tmp;
    @_[1 .. $#_] = ($in, $out, $data, $error, $alertLevel, $alertDescription);
    return $rc;
}

ppmhtml/site/lib/Crypt/MatrixSSL.html  view on Meta::CPAN

 %SSL_alertDescription</pre>
<p>
</p>
<hr />
<h1><a name="functions">FUNCTIONS</a></h1>
<dl>
<dt><strong><a name="matrixssldecode" class="item"><strong>matrixSslDecode</strong>( $ssl, $inBuf, $outBuf, $error, $alertLevel, $alertDescription )</a></strong></dt>

<dd>
<p>$inBuf and $outBuf are usual string scalars, not (sslBuf_t *) as in C interface.</p>
<p>After succesfull decoding one packet, <a href="#matrixssldecode"><code>matrixSslDecode()</code></a> will cut decoded
packet from $inBuf's beginning.</p>
<p>Reply SSL packets or application data will be appended to $outBuf, if any.</p>
<p>To convert error/alert codes into text use exported hashes:</p>
<pre>
 <span class="variable">$SSL_alertDescription</span><span class="operator">{</span> <span class="variable">$error</span> <span class="operator">}</span>
 <span class="variable">$SSL_alertLevel</span><span class="operator">{</span> <span class="variable">$alertLevel</span> <span class="operator">}</span>
 <span class="variable">$SSL_alertDescription</span><span class="operator">{</span> <span class="variable">$alertDescription</span> <span class="operator">}</span>
</pre>
</dd>
<dt><strong><a name="matrixsslencode" class="item"><strong>matrixSslEncode</strong>( $ssl, $inBuf, $outBuf )</a></strong></dt>

sample_functions.pl  view on Meta::CPAN

            my $s = substr($appOut, 0, $SSL_MAX_PLAINTEXT_LEN, q{});
            matrixSslEncode($ssl, $s, $out)
                >= 0 or die 'matrixSslEncode';
        }
    }
    @_[1 .. $#_] = ($in, $out, $appIn, $appOut, $handshakeIsComplete);
    return $err;
}

# Wrapper for matrixSslDecode() to separate two kind of output buffers -
# SSL packets which should be sent to other side and decoded application data:
#   $out param will contain SSL packets.
#   $data param will contain decoded application data.
# TODO  Realize this in XS?
sub matrixSslDecode2 {
    my ($ssl, $in, $out, $data, $error, $alertLevel, $alertDescription) = @_;
    my $rc = matrixSslDecode($ssl, $in, my $tmp=q{},
        $error, $alertLevel, $alertDescription);
    ($rc == $SSL_PROCESS_DATA ? $data : $out) .= $tmp;
    @_[1 .. $#_] = ($in, $out, $data, $error, $alertLevel, $alertDescription);
    return $rc;
}

t/client_server.t  view on Meta::CPAN

    >= 0 or die 'matrixSslEncode (client)';
ok(length $tmp < length $client2server,
    'matrixSslEncode append to output buffer');

my ($rc, $error, $alertLevel, $alertDescription);
$rc = matrixSslDecode($Server_SSL, $client2server, $server2client,
    $error, $alertLevel, $alertDescription);
is($rc, $SSL_PROCESS_DATA,
    'matrixSslDecode return SSL_PROCESS_DATA');
is($server2client, $s,
    '... first string decoded ok');
$rc = matrixSslDecode($Server_SSL, $client2server, $server2client,
    $error, $alertLevel, $alertDescription);
is($rc, $SSL_PROCESS_DATA,
    'matrixSslDecode return SSL_PROCESS_DATA');
is($server2client, $s.$s,
    '... second string decoded ok, matrixSslDecode append to output buffer');
is(length($client2server), 0,
    'no more data for decoding');

# SSL_MAX_PLAINTEXT_LEN

$s = 'abc' x 1234567;
$tmp = $s;
$client2server = $server2client = q{};
while (length $tmp) {
    $rc = matrixSslEncode($Client_SSL,
        substr($tmp, 0, $SSL_MAX_PLAINTEXT_LEN, q{}), $client2server)
        >= 0 or die 'matrixSslEncode up to SSL_MAX_PLAINTEXT_LEN';
}
while (length $client2server) {
    matrixSslDecode($Server_SSL, $client2server, $server2client,
        $error, $alertLevel, $alertDescription)
        == $SSL_PROCESS_DATA or die 'matrixSslDecode return non- SSL_PROCESS_DATA';
}
ok($server2client eq $s,
    'string split into SSL_MAX_PLAINTEXT_LEN chains decoded ok');

# More than SSL_MAX_PLAINTEXT_LEN

$s = 'x' x ($SSL_MAX_PLAINTEXT_LEN+1);
$client2server = $server2client = q{};
$rc = matrixSslEncode($Client_SSL, $s, $client2server);
ok($rc >= 0,
    'matrixSslEncode SSL_MAX_PLAINTEXT_LEN+1');
$rc = matrixSslDecode($Server_SSL, $client2server, $server2client,
    $error, $alertLevel, $alertDescription);

t/leak.t  view on Meta::CPAN

    matrixSslEncode($Client_SSL, $s, $client2server)
        >= 0 or die diag sprintf 'matrixSslEncode (client)';
    matrixSslEncode($Client_SSL, $s, $client2server)
        >= 0 or die diag sprintf 'matrixSslEncode (client)';

    my ($rc, $error, $alertLevel, $alertDescription);
    matrixSslDecode($Server_SSL, $client2server, $server2client,
        $error, $alertLevel, $alertDescription)
        == $SSL_PROCESS_DATA or die diag sprintf 'matrixSslDecode (first)';
    $server2client
        eq $s or die diag sprintf 'first string decoded incorrectly';
    matrixSslDecode($Server_SSL, $client2server, $server2client,
        $error, $alertLevel, $alertDescription)
        == $SSL_PROCESS_DATA or die diag sprintf 'matrixSslDecode (second)';;
    $server2client
        eq $s.$s or die diag sprintf 'second string decoded incorrectly or was not appended to output buffer';
    length($client2server)
        == 0 or die diag sprintf 'client2server non-empty';

    matrixSslDeleteSession($Server_SSL);
    matrixSslGetSessionId($Client_SSL, $Client_sessionId)
        == 0 or die diag sprintf 'matrixSslGetSessionId';
    matrixSslDeleteSession($Client_SSL);
    matrixSslFreeSessionId($Client_sessionId);
}



( run in 0.309 second using v1.01-cache-2.11-cpan-26ccb49234f )