/** * \file funcrypt.c * * \brief Functions for cryptographic stuff in softcode * * */ #include "copyrite.h" #include "config.h" #include <time.h> #include <string.h> #include <ctype.h> #include "conf.h" #include "case.h" #include "externs.h" #include "version.h" #include "extchat.h" #include "htab.h" #include "flags.h" #include "dbdefs.h" #include "parse.h" #include "function.h" #include "command.h" #include "game.h" #include "attrib.h" #include "ansi.h" #include "match.h" #ifdef HAS_OPENSSL #include <openssl/sha.h> #include <openssl/evp.h> #else #include "shs.h" #endif #include "confmagic.h" static char *crunch_code(char *code); static char *crypt_code(char *code, char *text, int type); #ifdef HAS_OPENSSL static void safe_hexchar(unsigned char c, char *buff, char **bp); #endif static void safe_sha0(const char *text, size_t len, char *buff, char **bp); /* Copy over only alphanumeric chars */ static char * crunch_code(char *code) { char *in; char *out; static char output[BUFFER_LEN]; out = output; in = code; while (*in) { while (*in == ESC_CHAR) { while (*in && *in != 'm') in++; in++; /* skip 'm' */ } if ((*in >= 32) && (*in <= 126)) { *out++ = *in; } in++; } *out = '\0'; return output; } static char * crypt_code(char *code, char *text, int type) { static char textbuff[BUFFER_LEN]; char codebuff[BUFFER_LEN]; int start = 32; int end = 126; int mod = end - start + 1; char *p, *q, *r; if (!text && !*text) return (char *) ""; strcpy(codebuff, crunch_code(code)); if (!code || !*code || !codebuff || !*codebuff) return text; textbuff[0] = '\0'; p = text; q = codebuff; r = textbuff; /* Encryption: Simply go through each character of the text, get its ascii * value, subtract start, add the ascii value (less start) of the * code, mod the result, add start. Continue */ while (*p) { if ((*p < start) || (*p > end)) { p++; continue; } if (type) *r++ = (((*p++ - start) + (*q++ - start)) % mod) + start; else *r++ = (((*p++ - *q++) + 2 * mod) % mod) + start; if (!*q) q = codebuff; } *r = '\0'; return textbuff; } static void safe_sha0(const char *text, size_t len, char *buff, char **bp) { #ifdef HAS_OPENSSL unsigned char hash[SHA_DIGEST_LENGTH]; int n; SHA((unsigned char *) text, len, hash); for (n = 0; n < SHA_DIGEST_LENGTH; n++) safe_hexchar(hash[n], buff, bp); #else SHS_INFO shsInfo; shsInfo.reverse_wanted = (BYTE) options.reverse_shs; shsInit(&shsInfo); shsUpdate(&shsInfo, (const BYTE *) text, len); shsFinal(&shsInfo); safe_format(buff, bp, "%0lx%0lx%0lx%0lx%0lx", shsInfo.digest[0], shsInfo.digest[1], shsInfo.digest[2], shsInfo.digest[3], shsInfo.digest[4]); #endif } FUNCTION(fun_encrypt) { char tbuff[BUFFER_LEN], *tp; char *pass; size_t len; ansi_string *as = parse_ansi_string(args[0]); pass = remove_markup(args[1], &len); tp = tbuff; safe_str(crypt_code(pass, as->text, 1), tbuff, &tp); *tp = '\0'; memcpy(as->text, tbuff, as->len); safe_ansi_string(as, 0, as->len, buff, bp); free_ansi_string(as); } FUNCTION(fun_decrypt) { char tbuff[BUFFER_LEN], *tp; char *pass; size_t len; ansi_string *as = parse_ansi_string(args[0]); pass = remove_markup(args[1], &len); tp = tbuff; safe_str(crypt_code(pass, as->text, 0), tbuff, &tp); *tp = '\0'; memcpy(as->text, tbuff, as->len + 1); safe_ansi_string(as, 0, as->len, buff, bp); free_ansi_string(as); } FUNCTION(fun_checkpass) { dbref it = match_thing(executor, args[0]); if (!(GoodObject(it) && IsPlayer(it))) { safe_str(T("#-1 NO SUCH PLAYER"), buff, bp); return; } safe_boolean(password_check(it, args[1]), buff, bp); } FUNCTION(fun_sha0) { safe_sha0(args[0], arglens[0], buff, bp); } FUNCTION(fun_digest) { #ifdef HAS_OPENSSL EVP_MD_CTX ctx; const EVP_MD *mp; unsigned char md[EVP_MAX_MD_SIZE]; unsigned int n, len = 0; if ((mp = EVP_get_digestbyname(args[0])) == NULL) { safe_str(T("#-1 UNSUPPORTED DIGEST TYPE"), buff, bp); return; } EVP_DigestInit(&ctx, mp); EVP_DigestUpdate(&ctx, args[1], arglens[1]); EVP_DigestFinal(&ctx, md, &len); for (n = 0; n < len; n++) { safe_hexchar(md[n], buff, bp); } #else if (strcmp(args[0], "sha") == 0) { safe_sha0(args[1], arglens[1], buff, bp); } else { safe_str(T("#-1 UNSUPPORTED DIGEST TYPE"), buff, bp); } #endif } #ifdef HAS_OPENSSL static void safe_hexchar(unsigned char c, char *buff, char **bp) { const char *digits = "0123456789abcdef"; if (*bp - buff < BUFFER_LEN - 1) { **bp = digits[c >> 4]; (*bp)++; } if (*bp - buff < BUFFER_LEN - 1) { **bp = digits[c & 0x0F]; (*bp)++; } } #endif