int GetBlowIniSwitch(const char *section, const char *key, const char *default_value) { char ini_value[10]; GetPrivateProfileString(section, key, default_value, ini_value, sizeof(ini_value), iniPath); if (isNoChar(*ini_value)) return 0; else return 1; }
retCode g__isNoChar(processPo P, ptrPo a) /* Number, other */ { ptrI x = deRefI(&a[1]); if (isvar(x)) return liberror(P, "__isNoChar", eINSUFARG); else { if (isNoChar((codePoint)IntVal(x))) return Ok; else return Fail; } }
/* * Decrypt a base64 cipher text (using key for target) */ int FiSH_decrypt(const SERVER_REC * serverRec, char *msg_ptr, const char *target, GString* decrypted_msg) { char contactName[CONTACT_SIZE] = ""; char theKey[KEYBUF_SIZE] = ""; char bf_dest[1000] = ""; char myMark[20] = ""; char *recoded; int msg_len, i, mark_broken_block = 0, action_found = 0, markPos; if (IsNULLorEmpty(msg_ptr) || decrypted_msg == NULL || IsNULLorEmpty(target)) return 0; if (settings_get_bool("process_incoming") == 0) return 0; if (strncmp(msg_ptr, "+OK ", 4) == 0) msg_ptr += 4; // TODO: Maybe remove this? else if (strncmp(msg_ptr, "mcps ", 5) == 0) msg_ptr += 5; else return 0; // don't process, blowcrypt-prefix not found // Verify base64 string msg_len = strlen(msg_ptr); if ((strspn(msg_ptr, B64) != (size_t) msg_len) || (msg_len < 12)) return 0; if (getIniSectionForContact(serverRec, target, contactName) == FALSE) return 0; if (getContactKey(contactName, theKey) == FALSE) return 0; // usually a received message does not exceed 512 chars, but we want to prevent evil buffer overflow if (msg_len >= (int)(sizeof(bf_dest) * 1.5)) msg_ptr[(int)(sizeof(bf_dest) * 1.5) - 20] = '\0'; // block-align blowcrypt strings if truncated by IRC server (each block is 12 chars long) // such a truncated block is destroyed and not needed anymore if (msg_len != (msg_len / 12) * 12) { msg_len = (msg_len / 12) * 12; msg_ptr[msg_len] = '\0'; strncpy(myMark, settings_get_str("mark_broken_block"), sizeof(myMark)); if (*myMark == '\0' || isNoChar(*myMark)) mark_broken_block = 0; else mark_broken_block = 1; } decrypt_string(theKey, msg_ptr, bf_dest, msg_len); ZeroMemory(theKey, KEYBUF_SIZE); if (*bf_dest == '\0') return 0; // don't process, decrypted msg is bad // recode message again, last time it was the encrypted message... if (settings_get_bool("recode") && serverRec != NULL) { recoded = recode_in(serverRec, bf_dest, target); if (recoded) { strncpy(bf_dest, recoded, sizeof(bf_dest)); ZeroMemory(recoded, strlen(recoded)); g_free(recoded); } } i = 0; while (bf_dest[i] != 0x0A && bf_dest[i] != 0x0D && bf_dest[i] != '\0') i++; bf_dest[i] = '\0'; // in case of wrong key, decrypted message might have control characters -> cut message if (strncmp(bf_dest, "\001ACTION ", 8) == 0) { // ACTION message found if (bf_dest[i - 1] == '\001') bf_dest[i - 1] = '\0'; // remove 0x01 control character action_found = 1; } // append broken-block-mark? if (mark_broken_block) strcat(bf_dest, myMark); // append crypt-mark? strncpy(myMark, settings_get_str("mark_encrypted"), sizeof(myMark)); if (*myMark != '\0') { markPos = settings_get_int("mark_position"); if (markPos == 0 || action_found) strcat(bf_dest, myMark); // append mark at the end (default for ACTION messages) else { // prefix mark i = strlen(myMark); memmove(bf_dest + i, bf_dest, strlen(bf_dest) + 1); strncpy(bf_dest, myMark, i); } } g_string_assign(decrypted_msg, bf_dest); ZeroMemory(bf_dest, sizeof(bf_dest)); return 1; }
/* * Decrypt a base64 cipher text (using key for target) */ int FiSH_decrypt(const SERVER_REC *server, char *msg_ptr, char *msg_bak, const char *target) { char contactName[CONTACT_SIZE]="", theKey[KEYBUF_SIZE]="", bf_dest[1000]=""; char myMark[20]="", markPos[20]="", *recoded; int msg_len, i, mark_broken_block=0, action_found=0; if (IsNULLorEmpty(msg_ptr) || msg_bak==NULL || IsNULLorEmpty(target)) return 0; if (GetBlowIniSwitch("FiSH", "process_incoming", "1") == 0) return 0; if (strncmp(msg_ptr, "+OK ", 4)==0) msg_ptr += 4; else if (strncmp(msg_ptr, "mcps ", 5)==0) msg_ptr += 5; else return 0; // don't process, blowcrypt-prefix not found // Verify base64 string msg_len=strlen(msg_ptr); if ((strspn(msg_ptr, B64) != (size_t)msg_len) || (msg_len < 12)) return 0; if (GetIniSectionForContact(server, target, contactName)==FALSE) return 0; if (LoadKeyForContact(contactName, theKey)==FALSE) return 0; // usually a received message does not exceed 512 chars, but we want to prevent evil buffer overflow if (msg_len >= (int)(sizeof(bf_dest)*1.5)) msg_ptr[(int)(sizeof(bf_dest)*1.5)-20]='\0'; // block-align blowcrypt strings if truncated by IRC server (each block is 12 chars long) // such a truncated block is destroyed and not needed anymore if (msg_len != (msg_len/12)*12) { msg_len=(msg_len/12)*12; msg_ptr[msg_len]='\0'; GetPrivateProfileString("FiSH", "mark_broken_block", " \002&\002", myMark, sizeof(myMark), iniPath); if (*myMark=='\0' || isNoChar(*myMark)) mark_broken_block=0; else mark_broken_block=1; } decrypt_string(theKey, msg_ptr, bf_dest, msg_len); ZeroMemory(theKey, KEYBUF_SIZE); if (*bf_dest=='\0') return 0; // don't process, decrypted msg is bad #ifdef FiSH_USE_IRSSI_RECODE // recode message again, last time it was the encrypted message... if (settings_get_bool("recode") && server!=NULL) { recoded = recode_in(server, bf_dest, target); if (recoded) { strncpy(bf_dest, recoded, sizeof(bf_dest)); ZeroMemory(recoded, strlen(recoded)); g_free(recoded); } } #endif i=0; while (bf_dest[i] != 0x0A && bf_dest[i] != 0x0D && bf_dest[i] != '\0') i++; bf_dest[i]='\0'; // in case of wrong key, decrypted message might have control characters -> cut message if (strncmp(bf_dest, "\001ACTION ", 8)==0) { // ACTION message found if (bf_dest[i-1] == '\001') bf_dest[i-1] = '\0'; // remove 0x01 control character action_found = 1; } // append broken-block-mark? if (mark_broken_block) strcat(bf_dest, myMark); // append crypt-mark? if (GetBlowIniSwitch(contactName, "mark_encrypted", "1") != 0) { GetPrivateProfileString("FiSH", "mark_encrypted", "", myMark, sizeof(myMark), iniPath); // global setting if (*myMark != '\0') { GetPrivateProfileString("FiSH", "mark_position", "0", markPos, sizeof(markPos), iniPath); if (*markPos=='0' || action_found) strcat(bf_dest, myMark); // append mark at the end (default for ACTION messages) else { // prefix mark i=strlen(myMark); memmove(bf_dest+i, bf_dest, strlen(bf_dest)+1); strncpy(bf_dest, myMark, i); } } } strcpy(msg_bak, bf_dest); // copy decrypted message back (overwriting the base64 cipher text) ZeroMemory(bf_dest, sizeof(bf_dest)); return 1; }