#include #include #include #include #include #include "encrypt.h" static void js_error_handler(JSContext *ctx, const char *msg, JSErrorReport *er); static JSBool executeJSFunction(JSContext *cx, const char *file, const char *function, uintN argc, jsval *argv, jsval *ret); JSClass globalObjectClass = { "global", 0, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char *encryptData(EncryptionTypes *type, const char *data){ JSRuntime *rt=NULL; JSContext *cx=NULL; jsval *parameters=NULL; jsval ret; JSString *stdinData=NULL; char *stdinDataBuffer; rt = JS_NewRuntime(1073741824); if (rt == NULL){ printf("Failed to start Spidermonkey, cannot perform encryption.\n"); return strdup(data); } cx = JS_NewContext(rt, 8192); if (cx == NULL){ JS_DestroyRuntime(rt); printf("Failed to start Spidermonkey, cannot perform encryption.\n"); return strdup(data); } JS_SetErrorReporter(cx, js_error_handler); /* Spidermonkey manages the memory space of it's strings, so we need to duplicate the passed string. * We must allocate the memory using Spidermonkey's JS_malloc function though, so that it is safe for * Spidermonkey to manage it. */ stdinDataBuffer = JS_malloc(cx, strlen(data)+1); memset(stdinDataBuffer, 0, strlen(data)+1); memcpy(stdinDataBuffer, data, strlen(data)); stdinData = JS_NewString(cx, stdinDataBuffer, strlen(stdinDataBuffer)); parameters=JS_malloc(cx, sizeof(*parameters)); parameters[0] = STRING_TO_JSVAL(stdinData); /* Execute the javascript file. */ if (executeJSFunction(cx, type->filePath, type->functionName, 1, parameters, &ret) == JS_TRUE){ JSString *retString = JS_ValueToString(cx, ret); char *encryptedString = JS_GetStringBytes(retString); char *returnedString; /* We duplicate the string returned by JS_GetStringBytes because when we clean up the * Runtime and Context the string pointed to by encryptedString will be cleaned up and * invalid. Therefore we need our own copy if we are going to use it after the cleanup. */ returnedString = strdup(encryptedString); JS_free(cx, parameters); JS_DestroyContext(cx); JS_DestroyRuntime(rt); return returnedString; } /* Cleanup Spidermonkey */ JS_free(cx, parameters); JS_DestroyContext(cx); JS_DestroyRuntime(rt); return strdup(data); } static JSBool executeJSFunction(JSContext *cx, const char *file, const char *function, uintN argc, jsval *argv, jsval *ret){ char *expandedFilename = expandTilda(file); struct stat fileDetails; JSObject *global=NULL; JSScript *script=NULL; if (stat(expandedFilename, &fileDetails) == -1){ printf("Encryption code file '%s' does not exist.\n", expandedFilename); free(expandedFilename); return JS_FALSE; } /* Create a global object */ global = JS_NewObject(cx, &globalObjectClass, NULL, NULL); if (global == NULL){ printf("Execution of encryptor failed: Cannot create global object.\n"); free(expandedFilename); return JS_FALSE; } JS_InitStandardClasses(cx, global); script = JS_CompileFile(cx, global, expandedFilename); if (script == NULL){ printf("Execution of encryptor failed: Cannot compile file '%s'.\n", expandedFilename); free(expandedFilename); return JS_FALSE; } if (JS_ExecuteScript(cx, global, script, ret) == JS_FALSE){ printf("Execution of encryptor failed: Cannot execute script file '%s'\n", expandedFilename); JS_DestroyScript(cx, script); free(expandedFilename); return JS_FALSE; } if (JS_CallFunctionName(cx, global, function, argc, argv, ret) == JS_FALSE){ printf("Execution of encryptor failed: Cannot execute function '%s' with string parameter.\n", function); JS_DestroyScript(cx, script); free(expandedFilename); return JS_FALSE; } JS_DestroyScript(cx, script); free(expandedFilename); return JS_TRUE; } static void js_error_handler(JSContext *ctx, const char *msg, JSErrorReport *er){ char *pointer=NULL; char *line=NULL; int len; if (er->linebuf != NULL){ len = er->tokenptr - er->linebuf + 1; pointer = malloc(len); memset(pointer, '-', len); pointer[len-1]='\0'; pointer[len-2]='^'; len = strlen(er->linebuf)+1; line = malloc(len); strncpy(line, er->linebuf, len); line[len-1] = '\0'; } else { len=0; pointer = malloc(1); line = malloc(1); pointer[0]='\0'; line[0] = '\0'; } while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n')){ line[len-1]='\0'; len--; } printf("JS Error: %s\nFile: %s:%u\n", msg, er->filename, er->lineno); if (line[0]){ printf("%s\n%s\n", line, pointer); } free(pointer); free(line); }