blob: 98ca1ff2a1f8e13678b023dcf025a526ef160e50 [file] [log] [blame]
/*
* cryp.c --- The encryption facility of websh
* nca-073-9
*
* Copyright (c) 1996-2000 by Netcetera AG.
* Copyright (c) 2001 by Apache Software Foundation.
* All rights reserved.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* @(#) $Id$
*
*/
#include <tcl.h>
#include "crypt.h"
#include "log.h"
#include "macros.h"
#include "nca_d.h"
/* ----------------------------------------------------------------------------
* init
* ------------------------------------------------------------------------- */
int crypt_Init(Tcl_Interp * interp)
{
CryptData *cryptData;
Tcl_Obj *tmp;
/* --------------------------------------------------------------------------
* interpreter running ?
* ----------------------------------------------------------------------- */
if (interp == NULL)
return TCL_ERROR;
/* --------------------------------------------------------------------------
* init internal data, and register with interp
* ----------------------------------------------------------------------- */
cryptData = createCryptData();
WebAssertData(interp, cryptData, "web::crypt", TCL_ERROR);
/* --------------------------------------------------------------------------
* register data with interp
* ----------------------------------------------------------------------- */
Tcl_SetAssocData(interp, WEB_CRYPT_ASSOC_DATA,
destroyCryptData, (ClientData) cryptData);
/* --------------------------------------------------------------------------
* register commands
* ----------------------------------------------------------------------- */
Tcl_CreateObjCommand(interp, "web::encrypt", Web_Encrypt, NULL, NULL);
Tcl_CreateObjCommand(interp, "web::decrypt", Web_Decrypt, NULL, NULL);
/* --------------------------------------------------------------------------
* default encrypt and decrypt chains
* ----------------------------------------------------------------------- */
tmp = Tcl_NewStringObj(WEB_ENCRYPTDEFAULT, -1);
cryptData->encryptChain = Tcl_NewListObj(1, &tmp);
Tcl_IncrRefCount(cryptData->encryptChain);
tmp = Tcl_NewStringObj(WEB_DECRYPTDEFAULT, -1);
cryptData->decryptChain = Tcl_NewListObj(1, &tmp);
Tcl_IncrRefCount(cryptData->decryptChain);
/* --------------------------------------------------------------------------
* done
* ----------------------------------------------------------------------- */
return TCL_OK;
}
/* ----------------------------------------------------------------------------
* createCryptData --
* ------------------------------------------------------------------------- */
CryptData *createCryptData()
{
CryptData *cryptData = NULL;
cryptData = WebAllocInternalData(CryptData);
if (cryptData != NULL) {
cryptData->encryptChain = NULL;
cryptData->decryptChain = NULL;
}
return cryptData;
}
/* ----------------------------------------------------------------------------
* destroyCryptData --
* ------------------------------------------------------------------------- */
void destroyCryptData(ClientData clientData, Tcl_Interp * interp)
{
CryptData *cryptData = NULL;
if (clientData != NULL) {
cryptData = (CryptData *) clientData;
WebDecrRefCountIfNotNull(cryptData->encryptChain);
WebDecrRefCountIfNotNull(cryptData->decryptChain);
WebFreeIfNotNull(cryptData);
}
}
/* --------------------------------------------------------------------------
* Web_Encrypt -- in: list, out: str
* ------------------------------------------------------------------------*/
int Web_Encrypt(ClientData clientData,
Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[])
{
WebAssertObjc(objc != 2, 1, "string");
return doencrypt(interp, objv[1], 0);
}
/* --------------------------------------------------------------------------
* Web_Decrypt
* ------------------------------------------------------------------------*/
int Web_Decrypt(ClientData clientData,
Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[])
{
/* ------------------------------------------------------------------------
* arg check: web::decrypt msg
* 0 1
* --------------------------------------------------------------------- */
WebAssertObjc(objc != 2, 1, "string");
return dodecrypt(interp, objv[1], 0);
}
/* --------------------------------------------------------------------------
* C API -- sets interp result
* ------------------------------------------------------------------------*/
int doencrypt(Tcl_Interp * interp, Tcl_Obj * in, int internal)
{
CryptData *cryptData = NULL;
int lobjc = -1;
Tcl_Obj **lobjv = NULL;
int i = -1;
if ((interp == NULL) || (in == NULL))
return TCL_ERROR;
cryptData =
(CryptData *) Tcl_GetAssocData(interp, WEB_CRYPT_ASSOC_DATA, NULL);
WebAssertData(interp, cryptData, "doencrypt", TCL_ERROR);
WebAssertData(interp, cryptData->encryptChain, "doencrypt", TCL_ERROR);
/* ------------------------------------------------------------------------
* get elements from encryptchain
* --------------------------------------------------------------------- */
if (Tcl_ListObjGetElements(interp, cryptData->encryptChain,
&lobjc, &lobjv) == TCL_ERROR) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::encrypt", WEBLOG_ERROR,
"error accessing encryptchain", NULL);
return TCL_ERROR;
}
/* --------------------------------------------------------------------------
* ... and loop
* ----------------------------------------------------------------------- */
for (i = 0; i <= lobjc; i++) {
int res = 0;
Tcl_Obj *cmd = NULL;
if (i < lobjc) {
if (lobjv[i] != NULL) {
cmd = Tcl_DuplicateObj(lobjv[i]);
Tcl_IncrRefCount(cmd);
} else {
cmd = NULL;
}
}
else {
if (!internal) {
Tcl_SetObjResult(interp, in);
return TCL_OK;
}
cmd = Tcl_NewListObj(0, NULL);
Tcl_IncrRefCount(cmd);
Tcl_ListObjAppendElement(interp, cmd,
Tcl_NewStringObj("web::list2uri", -1));
}
if (cmd != NULL) {
if (Tcl_ListObjAppendElement(interp, cmd, in) != TCL_OK) {
Tcl_DecrRefCount(cmd);
return TCL_ERROR;
}
res = Tcl_EvalObjEx(interp, cmd, TCL_EVAL_DIRECT);
Tcl_DecrRefCount(cmd);
switch (res) {
case TCL_OK:
return TCL_OK;
break;
case TCL_CONTINUE:
break;
default:
if (i < lobjc) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::encrypt", WEBLOG_ERROR,
"encrypt method \"", Tcl_GetString(lobjv[i]),
"\": ", Tcl_GetStringResult(interp), NULL);
}
return TCL_ERROR;
break;
}
}
}
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::encrypt", WEBLOG_ERROR,
"no matching encryption method found", NULL);
return TCL_ERROR;
}
/* --------------------------------------------------------------------------
* C API
* ------------------------------------------------------------------------*/
int dodecrypt(Tcl_Interp * interp, Tcl_Obj * in, int internal)
{
CryptData *cryptData = NULL;
int lobjc = -1;
Tcl_Obj **lobjv = NULL;
int i = -1;
if ((interp == NULL) || (in == NULL))
return TCL_ERROR;
cryptData =
(CryptData *) Tcl_GetAssocData(interp, WEB_CRYPT_ASSOC_DATA, NULL);
WebAssertData(interp, cryptData, "web::decrypt", TCL_ERROR);
WebAssertData(interp, cryptData->decryptChain, "web::decrypt", TCL_ERROR);
/* ------------------------------------------------------------------------
* loop over encryptchain
* --------------------------------------------------------------------- */
if (Tcl_ListObjGetElements(interp, cryptData->decryptChain,
&lobjc, &lobjv) == TCL_ERROR) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::decrypt", WEBLOG_ERROR,
"error accessing decryptchain", NULL);
return TCL_ERROR;
}
/* --------------------------------------------------------------------------
* now see what we got
* ----------------------------------------------------------------------- */
for (i = 0; i <= lobjc; i++) {
int res = 0;
Tcl_Obj *cmd = NULL;
if (i < lobjc) {
if (lobjv[i] != NULL) {
cmd = Tcl_DuplicateObj(lobjv[i]);
Tcl_IncrRefCount(cmd);
} else {
cmd = NULL;
}
}
else {
if (!internal) {
Tcl_SetObjResult(interp, in);
return TCL_OK;
}
cmd = Tcl_NewListObj(0, NULL);
Tcl_IncrRefCount(cmd);
Tcl_ListObjAppendElement(interp, cmd,
Tcl_NewStringObj("web::uri2list", -1));
}
if (cmd != NULL) {
if (Tcl_ListObjAppendElement(interp, cmd, in) != TCL_OK) {
Tcl_DecrRefCount(cmd);
return TCL_ERROR;
}
res = Tcl_EvalObjEx(interp, cmd, TCL_EVAL_DIRECT);
Tcl_DecrRefCount(cmd);
switch (res) {
case TCL_OK:
return TCL_OK;
break;
case TCL_CONTINUE:
break;
default:
if (i < lobjc) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::decrypt", WEBLOG_ERROR,
"decrypt method \"", Tcl_GetString(lobjv[i]),
"\": ", Tcl_GetStringResult(interp), NULL);
}
return TCL_ERROR;
break;
}
}
}
LOG_MSG(interp, WRITE_LOG | SET_RESULT,
__FILE__, __LINE__,
"web::decrypt", WEBLOG_ERROR,
"no matching decryption method found", NULL);
return TCL_ERROR;
}