Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Mailing Lists -> Oracle-L -> RE: C / external procedure puzzle for the C guru's

RE: C / external procedure puzzle for the C guru's

From: <George.Brennan_at_warnermusic.com>
Date: Wed, 31 May 2000 8:41:19 GMT
Message-Id: <10514.107221@fatcity.com>


Jared,

It's not something daft like

select 'abc' || chr(10) || 'cde' from dual;

only displays 'abc' because of hte linefeed ( chr(10)).

George

> -----Original Message-----
> From: "Jared Still" <jkstill_at_bcbso.com> [mailto:jkstill_at_bcbso.com]
> Sent: Tuesday, May 30, 2000 10:10 PM
> To: smtp_at_inl001@servers["Multiple recipients of list ORACLE-L"
> <ORACLE-L_at_fatcity.com>]
> Subject: C / external procedure puzzle for the C guru's
>
>
>
>
> First off let me say 'I am not a C programmer'.
>
> That disclaimer will hopefully insulate me from any
> flames for doing something stupid in C.
>
> I'm trying to build an encryption routine for use
> in Oracle, via external procedure calls.
>
> After digging through MetaLink for couple of hours I
> was able to get tnsnames.ora, sqlnet.ora and listener.ora
> to work properly for the external callouts.
>
> I dug up some RC4 encryption code in C from the web, and
> modified it for use in shared library.
>
> The original code always works correctly and as expected
> for command line use.
>
> When I modify it for use in a shared library, the function
> has the habit of returning data that is too short. It appears
> that whenever an encypted character is ascii character 10, the
> rest of the string is truncated.
>
> Whether this is a problem I built into the C code, or is
> an anomoly in the library spec, I'm not sure, though it is
> probably due to me bungling the string handling somehow.
>
> I'm hoping some of you C mavens that may have worked with
> external procedure callouts can help me out here, and point
> out any glaring errors I may have made.
>
> Thanks
>
> Jared
>
> PLATFORM:
>
> Sun E4500
> 2 Gig RAM
> 4 CPU
> Solaris 2.6
>
> Oracle version 8.1.6
>
> First, here are the additions to the listener.ora and
> tnsnames.ora files:
>
>
> LISTENER.ORA
>
> the only line that matters here is that
> added to the listener section:
>
> (address=
> (protocol=ipc)
> (key=extproc_key)
> )
>
> added to the SID list:
>
>
> (sid_desc=
> (sid_name=extproc_agent)
> (oracle_home = /obase/product/8.1.6)
> (program=extproc)
> )
>
> TNSNAMES.ORA
>
> this is the entire tnsnames.ora. Since
> we use oracle names, we don't usually have need
> for tnsnames
>
>
> extproc_connection_data.bcbso.tbg.org=
> (description=
> (address=(protocol=ipc)(key=extproc_key))
>
> (connect_data= (sid=extproc_agent))
> )
>
>
>
> SQLNET.ORA
>
>
> the only line that matters here is that this one,
> as it says to look in tnsnames.ora before checking
> with oracle names.
>
> NAMES.DIRECTORY_PATH = (TNSNAMES, ONAMES)
>
>
> This configuration all works fine.
>
>
> Below is the code used to build this.
>
> The files are :
>
> cl.sql which builds the package
> a single sql statement that fails
> rc4p.c which is the code for the shared library
> rc4.c which is the original C code
> rc4.h which is a header used by rc4p.c
>
> But first, here are the commands to build
> the shared library.
>
> cc -c rc4p.c
> ld -G -o rc4p.so rc4p.o
>
>
> ********************** cl.sql ***************************
>
> set echo on
>
>
> create or replace library librc4p as
> '/home/jkstill/articles/encryption/rc4/c/rc4p.so'
> /
>
> show errors
>
> create or replace package crypt
> is
> function rc4( key_in varchar2, data_in varchar2 )
> return varchar2;
> --pragma restrict_references( rc4, wnds, rnds, wnps );
> end;
> /
>
> show errors package crypt
>
> create or replace package body crypt
> is
>
> function rc4p( key_in varchar2, data_in in out varchar2 )
> return pls_integer is external
> library librc4p
> name "rc4p"
> language C;
>
> function rc4( key_in varchar2, data_in varchar2 )
> return varchar2
> is
> dummy pls_integer;
>
> v_data varchar2(500);
> clear_len integer;
> crypt_len integer;
>
> begin
>
> v_data := data_in;
> clear_len := length(v_data);
> dummy := rc4p( key_in, v_data );
>
> return v_data;
>
> end;
>
> end;
> /
>
>
> show errors package body crypt
>
>
> set echo off
>
> ********************** test SQL ***************************
>
> select crypt.rc4('cryptkey',(crypt.rc4(
> 'cryptkey','ALL_ALL_TABLES'))) from dual;
>
> ********************** rc4.h ***************************
>
> /* rc4.h */
> typedef struct rc4_key
> {
> unsigned char state[256];
> unsigned char x;
> unsigned char y;
> } rc4_key;
>
> void prepare_key(unsigned char *key_data_ptr,int
> key_data_len, rc4_key *key);
>
> void rc4(unsigned char *buffer_ptr,int buffer_len,rc4_key * key);
>
>
> ********************** rc4p.c ***************************
>
> #include <stdio.h>
>
> #define buf_size 1024
>
> /*rc4.c */
> #include "rc4.h"
> static void swap_byte(unsigned char *a, unsigned char *b);
>
> void prepare_key(unsigned char *key_data_ptr, int
> key_data_len, rc4_key *key)
> {
> unsigned char swapByte;
> unsigned char index1;
> unsigned char index2;
> unsigned char* state;
> short counter;
>
> state = &key->state[0];
> for(counter = 0; counter < 256; counter++)
> state[counter] = counter;
> key->x = 0;
> key->y = 0;
> index1 = 0;
> index2 = 0;
> for(counter = 0; counter < 256; counter++)
> {
> index2 = (key_data_ptr[index1] + state[counter] +
> index2) % 256;
> swap_byte(&state[counter], &state[index2]);
>
> index1 = (index1 + 1) % key_data_len;
> }
> }
>
> void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key)
> {
> unsigned char x;
> unsigned char y;
> unsigned char* state;
> unsigned char xorIndex;
> short counter;
>
> x = key->x;
> y = key->y;
>
> state = &key->state[0];
> for(counter = 0; counter < buffer_len; counter ++)
> {
> x = (x + 1) % 256;
> y = (state[x] + y) % 256;
> swap_byte(&state[x], &state[y]);
>
> xorIndex = (state[x] + state[y]) % 256;
>
> buffer_ptr[counter] ^= state[xorIndex];
> }
> key->x = x;
> key->y = y;
> }
>
> static void swap_byte(unsigned char *a, unsigned char *b)
> {
> unsigned char swapByte;
>
> swapByte = *a;
> *a = *b;
> *b = swapByte;
> }
>
>
>
> int rc4p( unsigned char* key_data, unsigned char *clear_text )
> {
> unsigned char seed[256];
> char data[512];
> char digit[5];
>
>
> int hex,i;
> int n, text_len;
> rc4_key key;
>
> strcpy(data,key_data);
> n = strlen(data);
> if (n&1)
> {
> strcat(data,"0");
> n++;
> }
> n/=2;
> strcpy(digit,"AA");
> digit[4]='\0';
> for (i=0;i<n;i++)
> {
> digit[2] = data[i*2];
> digit[3] = data[i*2+1];
> sscanf(digit,"%x",&hex);
> seed[i] = hex;
> }
>
> prepare_key(seed,n,&key);
>
> text_len = strlen(clear_text);
> rc4(clear_text,text_len,&key);
>
>
> return strlen(clear_text);
>
> }
>
>
>
>
> ********************** rc4.c ***************************
> #include <stdio.h>
>
> #define buf_size 1024
>
> typedef struct rc4_key
> {
> unsigned char state[256];
> unsigned char x;
> unsigned char y;
> } rc4_key;
>
> #define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t
>
> void prepare_key(unsigned char *key_data_ptr, int
> key_data_len, rc4_key *key)
> {
> int i;
> unsigned char t;
> unsigned char swapByte;
> unsigned char index1;
> unsigned char index2;
> unsigned char* state;
> short counter;
>
> state = &key->state[0];
> for(counter = 0; counter < 256; counter++)
> state[counter] = counter;
> key->x = 0;
> key->y = 0;
> index1 = 0;
> index2 = 0;
> for(counter = 0; counter < 256; counter++)
> {
> index2 = (key_data_ptr[index1] + state[counter] + index2) % 256;
> swap_byte(&state[counter], &state[index2]);
> index1 = (index1 + 1) % key_data_len;
> }
> }
>
> void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key)
> {
> unsigned char t;
> unsigned char x;
> unsigned char y;
> unsigned char* state;
> unsigned char xorIndex;
> short counter;
>
> x = key->x;
> y = key->y;
> state = &key->state[0];
> for(counter = 0; counter < buffer_len; counter++)
> {
> x = (x + 1) % 256;
> y = (state[x] + y) % 256;
> swap_byte(&state[x], &state[y]);
> xorIndex = (state[x] + state[y]) % 256;
> buffer_ptr[counter] ^= state[xorIndex];
> }
> key->x = x;
> key->y = y;
> }
>
> int main(int argc, char* argv[])
> {
> unsigned char seed[256];
> char data[512];
> unsigned char buf[buf_size];
> char digit[5];
> int hex, rd,i;
> int n;
> rc4_key key;
>
> if (argc < 2)
> {
> fprintf(stderr,"%s key <in >out\n",argv[0]);
> exit(1);
> }
> strcpy(data,argv[1]);
> n = strlen(data);
>
> if (n&1)
> {
> strcat(data,"0");
> n++;
> }
> n/=2;
> strcpy(digit,"AA");
> digit[4]='\0';
> for (i=0;i<n;i++)
> {
> digit[2] = data[i*2];
> digit[3] = data[i*2+1];
> sscanf(digit,"%x",&hex);
> seed[i] = hex;
> }
>
> prepare_key(seed,n,&key);
> rd = fread(buf,1,buf_size,stdin);
> while (rd>0)
> {
> rc4(buf,rd,&key);
> fwrite(buf,1,rd,stdout);
> rd = fread(buf,1,buf_size,stdin);
> }
> }
>
> ************************************************************
>
>
> --
> Author: Jared Still
> INET: jkstill_at_bcbso.com
>
> Fat City Network Services -- (858) 538-5051 FAX: (858) 538-5051
> San Diego, California -- Public Internet access / Mailing Lists
Received on Wed May 31 2000 - 03:41:19 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US