Пример #1
0
/*{
** Name: scu_xencode - encrypt a character string
**
** Description:
**      This function uses CI routines to encrypt a character string.
**	Since the character string is used to generate the key schedule,
**	the encryption is essentially one-way (you'd need to know the
**	password to decode the password....)  This routine was designed
**	to encrypt application_id passwords.
**
** Inputs:
**      SCU_XENCODE			the opcode to scf_call()
**      scf_cb                          control block in which is specified
**          .scf_ptr_union.scf_xpassword
**			                pointer to buffer to be encrypted
**          .scf_nbr_union.scf_xpasskey
**			                pointer to seed for key schedule
**          .scf_len_union.scf_xpwdlen
**					length of password and key seed
**
** Outputs:
**      scf_cb                          the same control block
**          .error                      the error control area
**              .err_code               E_SC_OK or ...
**					E_SC0261_XENCODE_BAD_PARM
**					E_SC0262_XENCODE_BAD_RESULT
**	Returns:
**	    E_DB_{OK, WARNING, ERROR, FATAL}
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	24-mar-89 (ralph)
**          Written for terminator
**	20-may-89 (ralph)
**	    Changed encryption to use separate key
**	06-jun-89 (ralph)
**	    Fixed unix compile problems
**	06-may-1993 (ralph)
**	    DELIM_IDENT:
**	    Translate key seed to lower case prior to encryption.
**	2-Jul-1993 (daveb)
**	    prototyped.
**	14-jul-93 (ed)
**	    replacing <dbms.h> by <gl.h> <sl.h> <iicommon.h> <dbdbms.h>
**	12-Sep-2007 (drivi01)
**	    Modified scu_xencode function to fix numerous bugs.
**	    The buffers for password manipulation shouldn't exceed
**	    the size of scb_xpassword field in SCF control block,
**	    otherwise the data will be truncated.
*/
DB_STATUS
scu_xencode(SCF_CB *scf_cb, SCD_SCB *scb )
{
    STATUS	status;
    CI_KS	KS;
    char	inbuffer[DB_PASSWORD_LENGTH+1];
    char	outbuffer[DB_PASSWORD_LENGTH+1];
    char	keybuffer[DB_PASSWORD_LENGTH];
    u_i2	i2_size;
    i4		longnat_size;
    i4		nat_size;
    char	*char_ptr;

#define	PASSINIT    "hjodvwHOJHOJhodh498032&*&*#)$&*jpkshghjlg58925fjkdjkpg"

    status = E_DB_OK;
    CLRDBERR(&scf_cb->scf_error);

    /* Ensure input parameter is okay */

    if ((scf_cb->scf_len_union.scf_xpwdlen <= 0)		||
	(scf_cb->scf_len_union.scf_xpwdlen >= sizeof(inbuffer)) ||
	(scf_cb->scf_nbr_union.scf_xpasskey  == NULL)		||
	(scf_cb->scf_ptr_union.scf_xpassword == NULL))
    {
	sc0ePut(NULL, E_SC0261_XENCODE_BAD_PARM, NULL, 0);
	SETDBERR(&scf_cb->scf_error, 0, E_SC0261_XENCODE_BAD_PARM);
	return(E_DB_ERROR);
    }


    /* Copy string to input buffer */

    MEmove(scf_cb->scf_len_union.scf_xpwdlen,
		 (PTR)scf_cb->scf_ptr_union.scf_xpassword,
		 (char)'\0',
		 sizeof(inbuffer),
		 (PTR)inbuffer);

    /* Copy key to key buffer */

    MEmove(scf_cb->scf_len_union.scf_xpwdlen,
		 (PTR)scf_cb->scf_nbr_union.scf_xpasskey,
		 (char)'?',
		 sizeof(keybuffer),
		 (PTR)keybuffer);

    /* Fold the key to lower case */

    for (nat_size = sizeof(keybuffer), char_ptr = keybuffer;
	 nat_size > 0;
	 nat_size = CMbytedec(nat_size, char_ptr), char_ptr = CMnext(char_ptr))
    {
	CMtolower(char_ptr, char_ptr);
    }

	 

    /* Remove white space from input string */

    nat_size = STzapblank(inbuffer, outbuffer);

    /* Check size */

    if ((nat_size <= 0) ||
	(nat_size > sizeof(outbuffer)-1))
    {
	sc0ePut(NULL, E_SC0261_XENCODE_BAD_PARM, NULL, 0);
	SETDBERR(&scf_cb->scf_error, 0, E_SC0261_XENCODE_BAD_PARM);
	return(E_DB_ERROR);
    }

    /* Initialize input buffer to "garbage" */

    MEmove(sizeof(PASSINIT), (PTR)PASSINIT, (char)'?',
		 sizeof(inbuffer), (PTR)inbuffer);

    /* Normalize the string back into input buffer */

    MEcopy((PTR)outbuffer, nat_size, (PTR)inbuffer);

    /* Reset output buffer to blanks */

    MEfill(sizeof(outbuffer),
		 (u_char)' ',
		 (PTR)outbuffer);

    /*
    ** First, encrypt the key seed using the string to encode.
    ** Then,  encrypt the string using the encrypted seed.
    ** This is done to prevent two roles with the same password
    ** from having the same encrypted value.
    ** Note that this makes the encryption one-way, since
    ** the password must be provided to decrypt the password!
    */

    /* Generate the key schedule to encrypt the key seed */

    (VOID)CIsetkey((PTR)inbuffer, KS);

    /* Encrypt the key seed */

    longnat_size = DB_PASSWORD_LENGTH;
    (VOID)CIencode((PTR)keybuffer, longnat_size, KS, (PTR)outbuffer);

    /* Generate the second key schedule */

    (VOID)CIsetkey((PTR)keybuffer, KS);

    /* Encode the string */

	longnat_size = DB_PASSWORD_LENGTH;
    (VOID)CIencode((PTR)inbuffer, longnat_size, KS, (PTR)outbuffer);

    /* Make sure it was really encoded */

    if ((char *)STskipblank(outbuffer, (i4)sizeof(outbuffer))
		!= NULL)
    {
	/* It was; copy result to caller's area */

	i2_size = scf_cb->scf_len_union.scf_xpwdlen;
	MEmove(sizeof(outbuffer), (PTR)outbuffer, (char)' ',
		     i2_size, (PTR)scf_cb->scf_ptr_union.scf_xpassword);
    }
    else
    {
	/* The encryption did not work; return an error */

	sc0ePut(NULL, E_SC0262_XENCODE_BAD_RESULT, NULL, 0);
	SETDBERR(&scf_cb->scf_error, 0, E_SC0262_XENCODE_BAD_RESULT);
	status = E_DB_ERROR;
    }

    return(status);
}
Пример #2
0
static STATUS
gcn_encode( char *key, u_i1 *mask, char *ipb, char *opb )
{
    CI_KS	ksch;
    char	kbuff[ CRYPT_SIZE + 1 ];
    char	tbuff[ 128 ];
    char	*ptr, *tmp = tbuff;
    i4		tsize = sizeof( tbuff );
    i4		len;
    bool	done;

    /*
    ** Validate input.
    */
    if ( key == NULL  ||  opb == NULL )  return( FAIL );

    if ( ipb == NULL  || *ipb == EOS )  
    {
	*opb = EOS;
	return( OK );
    }

    if ( mask == NULL )  mask = zeros;

    /*
    ** Ensure temp buffer is large enoush.
    */
    len = ((STlength(ipb) + (CRYPT_SIZE - 1)) / (CRYPT_SIZE - 1)) * CRYPT_SIZE;

    if ( len >= tsize )
    {
	tsize = len + 1;
    	tmp = (char *)MEreqmem( 0, tsize, FALSE, NULL );
	if ( ! tmp )  return( FAIL );
    }

    /*
    ** Adjust key to CRYPT_SIZE by duplication/truncation.
    */
    for( ptr = key, len = 0; len < CRYPT_SIZE; len++ )
    {
	if ( ! *ptr )  ptr = key;
	kbuff[ len ] = *ptr++ ^ mask[ len ];
    }

    kbuff[ len ] = EOS;
    CIsetkey( kbuff, ksch );

    /*
    ** The string to be encrypted must be a multiple of
    ** CRYPT_SIZE in length for the block encryption
    ** algorithm used by CIencode().  To provide some
    ** randomness in the output, the first character
    ** or each CRYPT_SIZE block is assigned a random
    ** value.  The remainder of the block is filled
    ** from the string to be encrypted.  If the final
    ** block is not filled, random values are used as
    ** padding.  A fixed delimiter separates the 
    ** original string and the padding (the delimiter 
    ** must always be present).
    */
    for( done = FALSE, len = 0; ! done  &&  (len + CRYPT_SIZE) < tsize; )
    {
	/*
	** First character in each encryption block is random.
	*/
	tmp[ len++ ] = (i4)(CSET_RANGE * MHrand()) + CSET_BASE;

	/*
	** Load string into remainder of encryption block.
	*/
        while( *ipb  &&  len % CRYPT_SIZE )  tmp[ len++ ] = *ipb++;

	/*
	** If encryption block not filled, fill with random padding.
	*/
	if ( len % CRYPT_SIZE )
	{
	    /*
	    ** Padding begins with fixed delimiter.
	    */
	    tmp[ len++ ] = CRYPT_DELIM;
	    done = TRUE;	/* Only done when delimiter appended */

	    /*
	    ** Fill encryption block with random padding.
	    */
	    while( len % CRYPT_SIZE )
		tmp[ len++ ] = (i4)(CSET_RANGE * MHrand()) + CSET_BASE;
	}
    }

    /*
    ** Encrypt the password and convert to text.
    */
    tmp[ len ] = EOS;
    CIencode( tmp, len, ksch, (PTR)tmp );
    CItotext( (u_char *)tmp, len, opb );

    if ( tmp != tbuff )  MEfree( (PTR)tmp );
    return( OK );
}