mirror of
https://github.com/hexchat/hexchat.git
synced 2024-11-05 10:42:33 +01:00
add fishlim plugin
This commit is contained in:
parent
895e3b6b40
commit
1a96ca3edd
@ -48,6 +48,7 @@ copy %DEPS_ROOT%\bin\libenchant.dll %XCHAT_DEST%
|
||||
xcopy /q /s /i %DEPS_ROOT%\lib\enchant\libenchant_myspell.dll %XCHAT_DEST%\lib\enchant\
|
||||
xcopy /q /s /i ..\plugins\checksum\xcchecksum.dll %XCHAT_DEST%\plugins\
|
||||
copy ..\plugins\doat\xcdoat.dll %XCHAT_DEST%\plugins
|
||||
copy ..\plugins\fishlim\xcfishlim.dll %XCHAT_DEST%\plugins
|
||||
copy ..\plugins\lua\xclua.dll %XCHAT_DEST%\plugins
|
||||
::copy ..\plugins\gtkpref\xcgtkpref.dll %XCHAT_DEST%\plugins
|
||||
copy ..\plugins\mpcinfo\xcmpcinfo.dll %XCHAT_DEST%\plugins
|
||||
|
@ -48,6 +48,7 @@ copy %DEPS_ROOT%\bin\libenchant.dll %XCHAT_DEST%
|
||||
xcopy /q /s /i %DEPS_ROOT%\lib\enchant\libenchant_myspell.dll %XCHAT_DEST%\lib\enchant\
|
||||
xcopy /q /s /i ..\plugins\checksum\xcchecksum.dll %XCHAT_DEST%\plugins\
|
||||
copy ..\plugins\doat\xcdoat.dll %XCHAT_DEST%\plugins
|
||||
copy ..\plugins\fishlim\xcfishlim.dll %XCHAT_DEST%\plugins
|
||||
copy ..\plugins\lua\xclua.dll %XCHAT_DEST%\plugins
|
||||
::copy ..\plugins\gtkpref\xcgtkpref.dll %XCHAT_DEST%\plugins
|
||||
copy ..\plugins\mpcinfo\xcmpcinfo.dll %XCHAT_DEST%\plugins
|
||||
|
@ -35,6 +35,7 @@ Name: "translations"; Description: "Translations"; Types: normal full custom; Fl
|
||||
Name: "plugins"; Description: "Plugins"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\checksum"; Description: "Checksum"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\doat"; Description: "Do At"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\fishlim"; Description: "FiSHLiM"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\mpcinfo"; Description: "mpcInfo"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\upd"; Description: "Update Checker"; Types: normal full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\winamp"; Description: "Winamp"; Types: full custom; Flags: disablenouninstallwarning
|
||||
@ -124,6 +125,7 @@ Source: "lib\gtk-2.0\modules\libgail.dll"; DestDir: "{app}\lib\gtk-2.0\modules";
|
||||
|
||||
Source: "plugins\xcchecksum.dll"; DestDir: "{app}\plugins"; Components: plugins\checksum
|
||||
Source: "plugins\xcdoat.dll"; DestDir: "{app}\plugins"; Components: plugins\doat
|
||||
Source: "plugins\xcfishlim.dll"; DestDir: "{app}\plugins"; Components: plugins\fishlim
|
||||
Source: "plugins\xcmpcinfo.dll"; DestDir: "{app}\plugins"; Components: plugins\mpcinfo
|
||||
Source: "plugins\xcupd.dll"; DestDir: "{app}\plugins"; Components: plugins\upd
|
||||
Source: "plugins\xcwinamp.dll"; DestDir: "{app}\plugins"; Components: plugins\winamp
|
||||
|
@ -34,6 +34,7 @@ Name: "translations"; Description: "Translations"; Types: normal full custom; Fl
|
||||
Name: "plugins"; Description: "Plugins"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\checksum"; Description: "Checksum"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\doat"; Description: "Do At"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\fishlim"; Description: "FiSHLiM"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\mpcinfo"; Description: "mpcInfo"; Types: full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\upd"; Description: "Update Checker"; Types: normal full custom; Flags: disablenouninstallwarning
|
||||
Name: "plugins\winamp"; Description: "Winamp"; Types: full custom; Flags: disablenouninstallwarning
|
||||
@ -123,6 +124,7 @@ Source: "lib\gtk-2.0\modules\libgail.dll"; DestDir: "{app}\lib\gtk-2.0\modules";
|
||||
|
||||
Source: "plugins\xcchecksum.dll"; DestDir: "{app}\plugins"; Components: plugins\checksum
|
||||
Source: "plugins\xcdoat.dll"; DestDir: "{app}\plugins"; Components: plugins\doat
|
||||
Source: "plugins\xcfishlim.dll"; DestDir: "{app}\plugins"; Components: plugins\fishlim
|
||||
Source: "plugins\xcmpcinfo.dll"; DestDir: "{app}\plugins"; Components: plugins\mpcinfo
|
||||
Source: "plugins\xcupd.dll"; DestDir: "{app}\plugins"; Components: plugins\upd
|
||||
Source: "plugins\xcwinamp.dll"; DestDir: "{app}\plugins"; Components: plugins\winamp
|
||||
|
16
plugins/fishlim/INSTALL
Normal file
16
plugins/fishlim/INSTALL
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
Install dependencies (on Debian/Ubuntu):
|
||||
|
||||
sudo apt-get install build-essential libglib2.0-dev libssl-dev
|
||||
|
||||
|
||||
Build the plugin with:
|
||||
|
||||
make
|
||||
|
||||
|
||||
Install with:
|
||||
|
||||
sudo make install
|
||||
|
||||
|
21
plugins/fishlim/LICENSE
Normal file
21
plugins/fishlim/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) 2010-2011 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
40
plugins/fishlim/Makefile
Normal file
40
plugins/fishlim/Makefile
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
OURCFLAGS = -Wall -Wextra -Wno-unused-parameter -std=c99 -pedantic `pkg-config --cflags glib-2.0 libcrypto` -DG_DISABLE_DEPRECATED=1 -fPIC $(CFLAGS)
|
||||
#OURLINKFLAGS = `pkg-config --libs glib-2.0 libcrypto` -shared -fPIC -Wl,-z,defs $(CFLAGS) $(LDFLAGS)
|
||||
OURLINKFLAGS = `pkg-config --libs glib-2.0 libcrypto` $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
BASE_OBJECTS = irc.o fish.o keystore.o misc.o
|
||||
PLUGIN_OBJECTS = $(BASE_OBJECTS) xchat_plugin.o
|
||||
TEST_OBJECTS = $(BASE_OBJECTS) test.o
|
||||
|
||||
all: fishlim.so test
|
||||
|
||||
fish.o: fish.h keystore.h misc.h
|
||||
irc.o: irc.h
|
||||
keystore.o: keystore.h irc.h fish.h misc.h
|
||||
misc.o: misc.h
|
||||
test.o: fish.h
|
||||
xchat_plugin.o: fish.h irc.h keystore.h
|
||||
|
||||
.c.o:
|
||||
$(CC) $(OURCFLAGS) -c $< -o $@
|
||||
|
||||
fishlim.so: $(PLUGIN_OBJECTS)
|
||||
$(CC) -shared $(OURLINKFLAGS) $(PLUGIN_OBJECTS) -o $@
|
||||
|
||||
test: $(TEST_OBJECTS)
|
||||
$(CC) $(OURLINKFLAGS) $(TEST_OBJECTS) -o $@
|
||||
|
||||
|
||||
.PHONY: all clean distclean install uninstall
|
||||
clean:
|
||||
-$(RM) -f $(PLUGIN_OBJECTS) $(TEST_OBJECTS) fishlim.so test
|
||||
distclean: clean
|
||||
|
||||
install: fishlim.so
|
||||
install -d $(DESTDIR)/usr/lib/xchat/plugins/
|
||||
install -m 644 fishlim.so $(DESTDIR)/usr/lib/xchat/plugins/
|
||||
uninstall:
|
||||
rm $(DESTDIR)/usr/lib/xchat/plugins/fishlim.so
|
||||
|
||||
|
44
plugins/fishlim/README
Normal file
44
plugins/fishlim/README
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
FiSHLiM
|
||||
|
||||
http://fishlim.slbdata.se/
|
||||
|
||||
|
||||
FiSHLiM is an XChat plugin for FiSH IRC encryption. It's my attempt at making
|
||||
a simple, lightweight and secure plugin for this encryption protocol.
|
||||
|
||||
For installation instructions, see the INSTALL file.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
Working:
|
||||
* Sending/receiving messages
|
||||
* Topic decryption
|
||||
* Using unecrypted keys / keys without a password from blow.ini
|
||||
* Pure protocol-level filtering (works with highlighting, nick coloring etc)
|
||||
* Partially encrypted messages (i.e. prefixed with nickname by a bouncer)
|
||||
|
||||
Not working:
|
||||
* Key exchange
|
||||
* Password-protected key storage
|
||||
* Topic encryption
|
||||
* Remote exploitation (hopefully!)
|
||||
|
||||
|
||||
Commands
|
||||
--------
|
||||
|
||||
/setkey [nick or #channel] password
|
||||
|
||||
Sets the encryption key for the nick or channel to password. The keys
|
||||
are stored in the configuration file in ~/.xchat2/blow.ini
|
||||
|
||||
|
||||
/delkey nick-or-#channel
|
||||
|
||||
Deletes the given nick or channel from the configuration file.
|
||||
|
||||
|
5
plugins/fishlim/bool.h
Normal file
5
plugins/fishlim/bool.h
Normal file
@ -0,0 +1,5 @@
|
||||
/* stdbool.h replacement for MSVC */
|
||||
#define false 0
|
||||
#define true 1
|
||||
#define bool _Bool
|
||||
typedef int _Bool;
|
192
plugins/fishlim/fish.c
Normal file
192
plugins/fishlim/fish.c
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <openssl/blowfish.h>
|
||||
|
||||
#include "keystore.h"
|
||||
#include "fish.h"
|
||||
|
||||
#define IB 64
|
||||
static const char fish_base64[64] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
static const signed char fish_unbase64[256] = {
|
||||
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB,IB,IB,
|
||||
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB,IB,IB,
|
||||
// ! " # $ % & ' ( ) * + , - . /
|
||||
IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB, 0, 1,
|
||||
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 10,11,IB,IB,IB,IB,IB,IB,
|
||||
// @ A B C D E F G H I J K L M N O
|
||||
IB,38,39,40,41,42,43,44, 45,46,47,48,49,50,51,52,
|
||||
// P Q R S T U V W X Y Z [ \ ] ^ _
|
||||
53,54,55,56,57,58,59,60, 61,62,63,IB,IB,IB,IB,IB,
|
||||
// ` a b c d e f g h i j k l m n o
|
||||
IB,12,13,14,15,16,17,18, 19,20,21,22,23,24,25,26,
|
||||
// p q r s t u v w x y z { | } ~ <del>
|
||||
27,28,29,30,31,32,33,34, 35,36,37,IB,IB,IB,IB,IB,
|
||||
};
|
||||
|
||||
#define GET_BYTES(dest, source) do { \
|
||||
*((dest)++) = ((source) >> 24) & 0xFF; \
|
||||
*((dest)++) = ((source) >> 16) & 0xFF; \
|
||||
*((dest)++) = ((source) >> 8) & 0xFF; \
|
||||
*((dest)++) = (source) & 0xFF; \
|
||||
} while (0);
|
||||
|
||||
|
||||
char *fish_encrypt(const char *key, size_t keylen, const char *message) {
|
||||
BF_KEY bfkey;
|
||||
size_t messagelen;
|
||||
size_t i;
|
||||
int j;
|
||||
char *encrypted;
|
||||
char *end;
|
||||
unsigned char bit;
|
||||
unsigned char word;
|
||||
unsigned char d;
|
||||
BF_set_key(&bfkey, keylen, (const unsigned char*)key);
|
||||
|
||||
messagelen = strlen(message);
|
||||
if (messagelen == 0) return NULL;
|
||||
encrypted = malloc(((messagelen-1)/8)*12 + 12 + 1); // each 8-byte block becomes 12 bytes
|
||||
end = encrypted;
|
||||
if (!encrypted) return NULL;
|
||||
|
||||
while (*message) {
|
||||
// Read 8 bytes (a Blowfish block)
|
||||
BF_LONG binary[2] = { 0, 0 };
|
||||
unsigned char c;
|
||||
for (i = 0; i < 8; i++) {
|
||||
c = message[i];
|
||||
binary[i >> 2] |= c << 8*(3 - (i&3));
|
||||
if (c == '\0') break;
|
||||
}
|
||||
message += 8;
|
||||
|
||||
// Encrypt block
|
||||
BF_encrypt(binary, &bfkey);
|
||||
|
||||
// Emit FiSH-BASE64
|
||||
bit = 0;
|
||||
word = 1;
|
||||
for (j = 0; j < 12; j++) {
|
||||
d = fish_base64[(binary[word] >> bit) & 63];
|
||||
*(end++) = d;
|
||||
bit += 6;
|
||||
if (j == 5) {
|
||||
bit = 0;
|
||||
word = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop if a null terminator was found
|
||||
if (c == '\0') break;
|
||||
}
|
||||
*end = '\0';
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
|
||||
char *fish_decrypt(const char *key, size_t keylen, const char *data) {
|
||||
BF_KEY bfkey;
|
||||
size_t i;
|
||||
char *decrypted;
|
||||
char *end;
|
||||
unsigned char bit;
|
||||
unsigned char word;
|
||||
unsigned char d;
|
||||
BF_set_key(&bfkey, keylen, (const unsigned char*)key);
|
||||
|
||||
decrypted = malloc(strlen(data)+1);
|
||||
end = decrypted;
|
||||
if (!decrypted) return NULL;
|
||||
|
||||
while (*data) {
|
||||
// Convert from FiSH-BASE64
|
||||
BF_LONG binary[2] = { 0, 0 };
|
||||
bit = 0;
|
||||
word = 1;
|
||||
for (i = 0; i < 12; i++) {
|
||||
d = fish_unbase64[(const unsigned char)*(data++)];
|
||||
if (d == IB) goto decrypt_end;
|
||||
binary[word] |= d << bit;
|
||||
bit += 6;
|
||||
if (i == 5) {
|
||||
bit = 0;
|
||||
word = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt block
|
||||
BF_decrypt(binary, &bfkey);
|
||||
|
||||
// Copy to buffer
|
||||
GET_BYTES(end, binary[0]);
|
||||
GET_BYTES(end, binary[1]);
|
||||
}
|
||||
|
||||
decrypt_end:
|
||||
*end = '\0';
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a message (see fish_decrypt). The key is searched for in the
|
||||
* key store.
|
||||
*/
|
||||
char *fish_encrypt_for_nick(const char *nick, const char *data) {
|
||||
char *key;
|
||||
char *encrypted;
|
||||
|
||||
// Look for key
|
||||
key = keystore_get_key(nick);
|
||||
if (!key) return NULL;
|
||||
|
||||
// Encrypt
|
||||
encrypted = fish_encrypt(key, strlen(key), data);
|
||||
|
||||
free(key);
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a message (see fish_decrypt). The key is searched for in the
|
||||
* key store.
|
||||
*/
|
||||
char *fish_decrypt_from_nick(const char *nick, const char *data) {
|
||||
char *key;
|
||||
char *decrypted;
|
||||
// Look for key
|
||||
key = keystore_get_key(nick);
|
||||
if (!key) return NULL;
|
||||
|
||||
// Decrypt
|
||||
decrypted = fish_decrypt(key, strlen(key), data);
|
||||
|
||||
free(key);
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
|
42
plugins/fishlim/fish.h
Normal file
42
plugins/fishlim/fish.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FISH_H
|
||||
#define FISH_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "bool.h"
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
char *fish_encrypt(const char *key, size_t keylen, const char *message);
|
||||
char *fish_decrypt(const char *key, size_t keylen, const char *data);
|
||||
char *fish_encrypt_for_nick(const char *nick, const char *data);
|
||||
char *fish_decrypt_from_nick(const char *nick, const char *data);
|
||||
|
||||
#endif
|
||||
|
||||
|
112
plugins/fishlim/irc.c
Normal file
112
plugins/fishlim/irc.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "irc.h"
|
||||
|
||||
/**
|
||||
* Parses an IRC message. The words array should contain the message splitted
|
||||
* at spaces. The prefix and command is extracted from the message, and
|
||||
* parameters_offset is set to the index of the first parameter.
|
||||
*/
|
||||
bool irc_parse_message(const char *words[],
|
||||
const char **prefix, const char **command,
|
||||
size_t *parameters_offset) {
|
||||
size_t w = 1;
|
||||
if (prefix) *prefix = NULL;
|
||||
if (command) *command = NULL;
|
||||
|
||||
// See if the message starts with a prefix (sender user)
|
||||
if (words[w][0] == ':') {
|
||||
if (prefix) *prefix = &words[w][1];
|
||||
w++;
|
||||
}
|
||||
|
||||
// Check command
|
||||
if (words[w][0] == '\0') return false;
|
||||
if (command) *command = words[w];
|
||||
w++;
|
||||
|
||||
*parameters_offset = w;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the nick part of a "IRC prefix", which can have any
|
||||
* of the following forms:
|
||||
*
|
||||
* nick
|
||||
* nick@host
|
||||
* nick!ident
|
||||
* nick!ident@host
|
||||
*/
|
||||
char *irc_prefix_get_nick(const char *prefix) {
|
||||
const char *end;
|
||||
char *nick;
|
||||
size_t length;
|
||||
|
||||
if (!prefix) return NULL;
|
||||
|
||||
// Find end of nick
|
||||
end = prefix;
|
||||
while (*end != '\0' && *end != '!' && *end != '@') end++;
|
||||
|
||||
// Allocate string
|
||||
length = end - prefix;
|
||||
nick = malloc(length+1);
|
||||
if (!nick) return NULL;
|
||||
|
||||
// Copy to string
|
||||
memcpy(nick, prefix, length);
|
||||
nick[length] = '\0';
|
||||
return nick;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two nick names. Return 0 if equal. Otherwise the return value is
|
||||
* less than zero if a is less than b or greater than zero if a is greater
|
||||
* than b.
|
||||
*/
|
||||
int irc_nick_cmp(const char *a, const char *b) {
|
||||
char ac;
|
||||
char bc;
|
||||
char diff;
|
||||
for (;;) {
|
||||
ac = *(a++);
|
||||
bc = *(b++);
|
||||
|
||||
// Change into IRC uppercase (see RFC 2812 section 2.2)
|
||||
if (ac >= 'a' && ac <= '~') ac &= ~0x20;
|
||||
if (bc >= 'a' && bc <= '~') bc &= ~0x20;
|
||||
|
||||
diff = ac - bc;
|
||||
if (diff) return diff;
|
||||
if (!ac) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
43
plugins/fishlim/irc.h
Normal file
43
plugins/fishlim/irc.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef IRC_H
|
||||
#define IRC_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "bool.h"
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
bool irc_parse_message(const char *words[],
|
||||
const char **prefix, const char **command,
|
||||
size_t *parameters_offset);
|
||||
char *irc_prefix_get_nick(const char *prefix);
|
||||
int irc_nick_cmp(const char *a, const char *b);
|
||||
|
||||
#endif
|
||||
|
||||
|
217
plugins/fishlim/keystore.c
Normal file
217
plugins/fishlim/keystore.c
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "irc.h"
|
||||
#include "fish.h"
|
||||
#include "misc.h"
|
||||
#include "keystore.h"
|
||||
|
||||
|
||||
static char *keystore_password = NULL;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the path to the key store file.
|
||||
*/
|
||||
static gchar *get_config_filename() {
|
||||
// TODO use xchat_get_info(ph, "xchatdirfs")
|
||||
const gchar *homedir = g_get_home_dir();
|
||||
return g_build_filename(homedir, ".xchat2", "blow.ini", NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the key store file: ~/.xchat2/blow.ini
|
||||
*/
|
||||
static GKeyFile *getConfigFile() {
|
||||
gchar *filename = get_config_filename();
|
||||
|
||||
GKeyFile *keyfile = g_key_file_new();
|
||||
g_key_file_load_from_file(keyfile, filename,
|
||||
G_KEY_FILE_KEEP_COMMENTS |
|
||||
G_KEY_FILE_KEEP_TRANSLATIONS, NULL);
|
||||
|
||||
g_free(filename);
|
||||
return keyfile;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the key store password, or the default.
|
||||
*/
|
||||
static const char *get_keystore_password() {
|
||||
return (keystore_password != NULL ?
|
||||
keystore_password :
|
||||
// Silly default value...
|
||||
"blowinikey");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a value for a nick/channel from blow.ini. Unlike
|
||||
* g_key_file_get_string, this function is case insensitive.
|
||||
*/
|
||||
static gchar *get_nick_value(GKeyFile *keyfile, const char *nick, const char *item) {
|
||||
gchar **group;
|
||||
gchar **groups = g_key_file_get_groups(keyfile, NULL);
|
||||
gchar *result = NULL;
|
||||
|
||||
for (group = groups; *group != NULL; group++) {
|
||||
if (!irc_nick_cmp(*group, nick)) {
|
||||
result = g_key_file_get_string(keyfile, *group, item, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev(groups);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts a key from the key store file.
|
||||
*/
|
||||
char *keystore_get_key(const char *nick) {
|
||||
// Get the key
|
||||
GKeyFile *keyfile = getConfigFile();
|
||||
gchar *value = get_nick_value(keyfile, nick, "key");
|
||||
g_key_file_free(keyfile);
|
||||
if (!value) return NULL;
|
||||
|
||||
if (strncmp(value, "+OK ", 4) != 0) {
|
||||
// Key is stored in plaintext
|
||||
return import_glib_string(value);
|
||||
} else {
|
||||
// Key is encrypted
|
||||
const char *encrypted = value+4;
|
||||
const char *password = get_keystore_password();
|
||||
char *decrypted = fish_decrypt(password, strlen(password), encrypted);
|
||||
g_free(value);
|
||||
return decrypted;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a nick and the associated key in the key store file.
|
||||
*/
|
||||
static bool delete_nick(GKeyFile *keyfile, const char *nick) {
|
||||
gchar **group;
|
||||
gchar **groups = g_key_file_get_groups(keyfile, NULL);
|
||||
bool ok = false;
|
||||
|
||||
for (group = groups; *group != NULL; group++) {
|
||||
if (!irc_nick_cmp(*group, nick)) {
|
||||
ok = g_key_file_remove_group(keyfile, *group, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev(groups);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the key store file to disk.
|
||||
*/
|
||||
static bool save_keystore(GKeyFile *keyfile) {
|
||||
char *filename;
|
||||
bool ok;
|
||||
// Serialize
|
||||
gsize file_length;
|
||||
gchar *file_data = g_key_file_to_data(keyfile, &file_length, NULL);
|
||||
if (!file_data) return false;
|
||||
|
||||
// Write to file
|
||||
filename = get_config_filename();
|
||||
ok = g_file_set_contents(filename, file_data, file_length, NULL);
|
||||
g_free(filename);
|
||||
g_free(file_data);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a key in the key store file.
|
||||
*/
|
||||
bool keystore_store_key(const char *nick, const char *key) {
|
||||
const char *password;
|
||||
char *encrypted;
|
||||
char *wrapped;
|
||||
bool ok = false;
|
||||
GKeyFile *keyfile = getConfigFile();
|
||||
|
||||
// Remove old key
|
||||
delete_nick(keyfile, nick);
|
||||
|
||||
// Add new key
|
||||
password = get_keystore_password();
|
||||
if (password) {
|
||||
// Encrypt the password
|
||||
encrypted = fish_encrypt(password, strlen(password), key);
|
||||
if (!encrypted) goto end;
|
||||
|
||||
// Prepend "OK+ "
|
||||
wrapped = g_strconcat("OK+ ", encrypted, NULL);
|
||||
g_free(encrypted);
|
||||
|
||||
// Store encrypted in file
|
||||
g_key_file_set_string(keyfile, nick, "key", wrapped);
|
||||
free(wrapped);
|
||||
} else {
|
||||
// Store unencrypted in file
|
||||
g_key_file_set_string(keyfile, nick, "key", key);
|
||||
}
|
||||
|
||||
// Save key store file
|
||||
ok = save_keystore(keyfile);
|
||||
|
||||
end:
|
||||
g_key_file_free(keyfile);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a nick from the key store.
|
||||
*/
|
||||
bool keystore_delete_nick(const char *nick) {
|
||||
GKeyFile *keyfile = getConfigFile();
|
||||
|
||||
// Delete entry
|
||||
bool ok = delete_nick(keyfile, nick);
|
||||
|
||||
// Save
|
||||
if (ok) save_keystore(keyfile);
|
||||
|
||||
g_key_file_free(keyfile);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
void keystore_secure_free(void *ptr, size_t size) {
|
||||
secure_erase(ptr, size);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
42
plugins/fishlim/keystore.h
Normal file
42
plugins/fishlim/keystore.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef KEYSTORE_H
|
||||
#define KEYSTORE_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "bool.h"
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
char *keystore_get_key(const char *nick);
|
||||
int keystore_store_key(const char *nick, const char *key);
|
||||
bool keystore_delete_nick(const char *nick);
|
||||
|
||||
void keystore_secure_free(void *ptr, size_t size);
|
||||
|
||||
#endif
|
||||
|
30
plugins/fishlim/makefile.mak
Normal file
30
plugins/fishlim/makefile.mak
Normal file
@ -0,0 +1,30 @@
|
||||
include "..\..\src\makeinc.mak"
|
||||
|
||||
TARGET = xcfishlim.dll
|
||||
|
||||
CFLAGS = $(CFLAGS)
|
||||
|
||||
FISHLIM_OBJECTS = \
|
||||
fish.obj \
|
||||
irc.obj \
|
||||
keystore.obj \
|
||||
misc.obj \
|
||||
xchat_plugin.obj
|
||||
|
||||
all: $(FISHLIM_OBJECTS) fishlim.def
|
||||
link $(LDFLAGS) $(LIBS) /dll /out:xcfishlim.dll /def:fishlim.def $(FISHLIM_OBJECTS)
|
||||
|
||||
fishlim.def:
|
||||
echo EXPORTS > fishlim.def
|
||||
echo xchat_plugin_init >> fishlim.def
|
||||
echo xchat_plugin_deinit >> fishlim.def
|
||||
echo xchat_plugin_get_info >> fishlim.def
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) $(GLIB) /I.. /c $<
|
||||
|
||||
clean:
|
||||
del *.obj
|
||||
del *.dll
|
||||
del *.exp
|
||||
del *.lib
|
54
plugins/fishlim/misc.c
Normal file
54
plugins/fishlim/misc.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
void secure_erase(void *ptr, size_t size) {
|
||||
// "volatile" prevents this code from being optimized away
|
||||
volatile char* volptr = ptr;
|
||||
while (size--) *volptr++ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-allocates a string with the native allocator.
|
||||
*/
|
||||
char *import_glib_string(gchar *gstr) {
|
||||
size_t size;
|
||||
char *native;
|
||||
if (g_mem_is_system_malloc()) return gstr;
|
||||
|
||||
size = strlen(gstr)+1;
|
||||
native = malloc(size);
|
||||
memcpy(native, gstr, size);
|
||||
|
||||
secure_erase(gstr, size);
|
||||
g_free(gstr);
|
||||
return native;
|
||||
}
|
||||
|
||||
|
36
plugins/fishlim/misc.h
Normal file
36
plugins/fishlim/misc.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MISC_H
|
||||
#define MISC_H
|
||||
|
||||
void secure_erase(void *ptr, size_t size);
|
||||
|
||||
#ifdef __G_LIB_H__
|
||||
char *import_glib_string(gchar *gstr);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
83
plugins/fishlim/test.c
Normal file
83
plugins/fishlim/test.c
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "fish.h"
|
||||
|
||||
static int decrypt(int nick_count, char *nicks[]) {
|
||||
char encrypted[8192];
|
||||
while (fgets(encrypted, sizeof(encrypted), stdin)) {
|
||||
char *msg;
|
||||
for (int i = 0; i < nick_count; i++) {
|
||||
msg = fish_decrypt_from_nick(nicks[i], encrypted);
|
||||
if (msg) goto success;
|
||||
}
|
||||
fprintf(stderr, "None of the recipients were found in the key store!\n");
|
||||
return 1;
|
||||
success:
|
||||
fprintf(stderr, "Decrypted text >>>%s<<<\n", msg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encrypt(int nick_count, char *nicks[]) {
|
||||
char message[8192];
|
||||
while (fgets(message, sizeof(message), stdin)) {
|
||||
// Remove newline character
|
||||
char *newline = strchr(message, '\n');
|
||||
if (newline) *newline = '\0';
|
||||
|
||||
bool error = false;
|
||||
for (int i = 0; i < nick_count; i++) {
|
||||
char *encrypted = fish_encrypt_for_nick(nicks[i], message);
|
||||
if (encrypted) {
|
||||
fprintf(stderr, "Encrypted [%s]: >>>%s<<<\n", nicks[i], encrypted);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
fprintf(stderr, "Some of the recipients were't found in the key store!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s [-e] nick...\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "-e") == 0) {
|
||||
return encrypt(argc-2, &argv[2]);
|
||||
} else {
|
||||
return decrypt(argc-1, &argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
278
plugins/fishlim/xchat_plugin.c
Normal file
278
plugins/fishlim/xchat_plugin.c
Normal file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2010-2011 Samuel Lidén Borell <samuel@slbdata.se>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// #pragma GCC visibility push(default)
|
||||
#include "xchat-plugin.h"
|
||||
#define XCHAT_MAX_WORDS 32
|
||||
// #pragma GCC visibility pop
|
||||
|
||||
//#define EXPORT __attribute((visibility("default")))
|
||||
//#define EXPORT
|
||||
|
||||
#include "fish.h"
|
||||
#include "keystore.h"
|
||||
#include "irc.h"
|
||||
|
||||
static const char plugin_name[] = "FiSHLiM";
|
||||
static const char plugin_desc[] = "Encryption plugin for the FiSH protocol. Less is More!";
|
||||
static const char plugin_version[] = "0.0.13";
|
||||
|
||||
static const char usage_setkey[] = "Usage: SETKEY [<nick or #channel>] <password>, sets the key for a channel or nick";
|
||||
static const char usage_delkey[] = "Usage: DELKEY <nick or #channel>, deletes the key for a channel or nick";
|
||||
|
||||
static xchat_plugin *ph;
|
||||
|
||||
|
||||
/**
|
||||
* Appends data to a string. Returns true if there was sufficient memory.
|
||||
* Frees *s and returns false if an error occurs.
|
||||
*/
|
||||
static bool append(char **s, size_t *length, const char *data) {
|
||||
size_t datalen = strlen(data);
|
||||
char *extended = realloc(*s, *length + datalen + 1);
|
||||
if (!extended) {
|
||||
free(*s);
|
||||
return false;
|
||||
}
|
||||
memcpy(extended + *length, data, datalen + 1);
|
||||
*s = extended;
|
||||
*length += datalen;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*static int handle_debug(char *word[], char *word_eol[], void *userdata) {
|
||||
xchat_printf(ph, "debug incoming: ");
|
||||
for (size_t i = 1; word[i] != NULL && word[i][0] != '\0'; i++) {
|
||||
xchat_printf(ph, ">%s< ", word[i]);
|
||||
}
|
||||
xchat_printf(ph, "\n");
|
||||
return XCHAT_EAT_NONE;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Called when a message is to be sent.
|
||||
*/
|
||||
static int handle_outgoing(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *own_nick;
|
||||
// Encrypt the message if possible
|
||||
const char *channel = xchat_get_info(ph, "channel");
|
||||
char *encrypted = fish_encrypt_for_nick(channel, word_eol[1]);
|
||||
if (!encrypted) return XCHAT_EAT_NONE;
|
||||
|
||||
// Display message
|
||||
own_nick = xchat_get_info(ph, "nick");
|
||||
xchat_emit_print(ph, "Your Message", own_nick, word_eol[1], NULL);
|
||||
|
||||
// Send message
|
||||
xchat_commandf(ph, "PRIVMSG %s :+OK %s", channel, encrypted);
|
||||
|
||||
free(encrypted);
|
||||
return XCHAT_EAT_XCHAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a channel message or private message is received.
|
||||
*/
|
||||
static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *prefix;
|
||||
const char *command;
|
||||
const char *recipient;
|
||||
const char *encrypted;
|
||||
const char *peice;
|
||||
char *sender_nick;
|
||||
char *decrypted;
|
||||
char *message;
|
||||
size_t w;
|
||||
size_t ew;
|
||||
size_t uw;
|
||||
size_t length;
|
||||
|
||||
if (!irc_parse_message((const char **)word, &prefix, &command, &w))
|
||||
return XCHAT_EAT_NONE;
|
||||
|
||||
// Topic (command 332) has an extra parameter
|
||||
if (!strcmp(command, "332")) w++;
|
||||
|
||||
// Look for encrypted data
|
||||
ew;
|
||||
for (ew = w+1; ew < XCHAT_MAX_WORDS-1; ew++) {
|
||||
const char *s = (ew == w+1 ? word[ew]+1 : word[ew]);
|
||||
if (strcmp(s, "+OK") == 0) goto has_encrypted_data;
|
||||
}
|
||||
return XCHAT_EAT_NONE;
|
||||
has_encrypted_data: ;
|
||||
// Extract sender nick and recipient nick/channel
|
||||
sender_nick = irc_prefix_get_nick(prefix);
|
||||
recipient = word[w];
|
||||
|
||||
// Try to decrypt with these (the keys are searched for in the key store)
|
||||
encrypted = word[ew+1];
|
||||
decrypted = fish_decrypt_from_nick(recipient, encrypted);
|
||||
if (!decrypted) decrypted = fish_decrypt_from_nick(sender_nick, encrypted);
|
||||
|
||||
// Check for error
|
||||
if (!decrypted) goto decrypt_error;
|
||||
|
||||
// Build unecrypted message
|
||||
message = NULL;
|
||||
length = 0;
|
||||
if (!append(&message, &length, "RECV")) goto decrypt_error;
|
||||
|
||||
for (uw = 1; uw < XCHAT_MAX_WORDS; uw++) {
|
||||
if (word[uw][0] != '\0' && !append(&message, &length, " ")) goto decrypt_error;
|
||||
|
||||
if (uw == ew) {
|
||||
// Add the encrypted data
|
||||
peice = decrypted;
|
||||
uw++; // Skip "OK+"
|
||||
} else {
|
||||
// Add unencrypted data (for example, a prefix from a bouncer or bot)
|
||||
peice = (uw == w+1 ? word[uw]+1 : word[uw]);
|
||||
}
|
||||
|
||||
if (!append(&message, &length, peice)) goto decrypt_error;
|
||||
}
|
||||
free(decrypted);
|
||||
|
||||
// Simulate unencrypted message
|
||||
//xchat_printf(ph, "simulating: %s\n", message);
|
||||
xchat_command(ph, message);
|
||||
|
||||
free(message);
|
||||
free(sender_nick);
|
||||
return XCHAT_EAT_XCHAT;
|
||||
|
||||
decrypt_error:
|
||||
free(decrypted);
|
||||
free(sender_nick);
|
||||
return XCHAT_EAT_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command handler for /setkey
|
||||
*/
|
||||
static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *nick;
|
||||
const char *key;
|
||||
|
||||
// Check syntax
|
||||
if (*word[2] == '\0') {
|
||||
xchat_printf(ph, "%s\n", usage_setkey);
|
||||
return XCHAT_EAT_XCHAT;
|
||||
}
|
||||
|
||||
if (*word[3] == '\0') {
|
||||
// /setkey password
|
||||
nick = xchat_get_info(ph, "channel");
|
||||
key = word_eol[2];
|
||||
} else {
|
||||
// /setkey #channel password
|
||||
nick = word[2];
|
||||
key = word_eol[3];
|
||||
}
|
||||
|
||||
// Set password
|
||||
if (keystore_store_key(nick, key)) {
|
||||
xchat_printf(ph, "Stored key for %s\n", nick);
|
||||
} else {
|
||||
xchat_printf(ph, "\00305Failed to store key in blow.ini\n", nick, key);
|
||||
}
|
||||
|
||||
return XCHAT_EAT_XCHAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command handler for /delkey
|
||||
*/
|
||||
static int handle_delkey(char *word[], char *word_eol[], void *userdata) {
|
||||
const char *nick;
|
||||
|
||||
// Check syntax
|
||||
if (*word[2] == '\0' || *word[3] != '\0') {
|
||||
xchat_printf(ph, "%s\n", usage_delkey);
|
||||
return XCHAT_EAT_XCHAT;
|
||||
}
|
||||
|
||||
nick = word_eol[2];
|
||||
|
||||
// Delete the given nick from the key store
|
||||
if (keystore_delete_nick(nick)) {
|
||||
xchat_printf(ph, "Deleted key for %s\n", nick);
|
||||
} else {
|
||||
xchat_printf(ph, "\00305Failed to delete key in blow.ini!\n", nick);
|
||||
}
|
||||
|
||||
return XCHAT_EAT_XCHAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin name version information.
|
||||
*/
|
||||
void xchat_plugin_get_info(const char **name, const char **desc,
|
||||
const char **version, void **reserved) {
|
||||
*name = plugin_name;
|
||||
*desc = plugin_desc;
|
||||
*version = plugin_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin entry point.
|
||||
*/
|
||||
int xchat_plugin_init(xchat_plugin *plugin_handle,
|
||||
const char **name,
|
||||
const char **desc,
|
||||
const char **version,
|
||||
char *arg) {
|
||||
ph = plugin_handle;
|
||||
|
||||
/* Send our info to XChat */
|
||||
*name = plugin_name;
|
||||
*desc = plugin_desc;
|
||||
*version = plugin_version;
|
||||
|
||||
/* Register commands */
|
||||
xchat_hook_command(ph, "SETKEY", XCHAT_PRI_NORM, handle_setkey, usage_setkey, NULL);
|
||||
xchat_hook_command(ph, "DELKEY", XCHAT_PRI_NORM, handle_delkey, usage_delkey, NULL);
|
||||
|
||||
/* Add handlers */
|
||||
xchat_hook_command(ph, "", XCHAT_PRI_NORM, handle_outgoing, NULL, NULL);
|
||||
xchat_hook_server(ph, "NOTICE", XCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
xchat_hook_server(ph, "PRIVMSG", XCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
//xchat_hook_server(ph, "RAW LINE", XCHAT_PRI_NORM, handle_debug, NULL);
|
||||
xchat_hook_server(ph, "TOPIC", XCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
xchat_hook_server(ph, "332", XCHAT_PRI_NORM, handle_incoming, NULL);
|
||||
|
||||
xchat_printf (ph, "%s plugin loaded\n", plugin_name);
|
||||
/* Return success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xchat_plugin_deinit(void) {
|
||||
xchat_printf (ph, "%s plugin unloaded\n", plugin_name);
|
||||
return 1;
|
||||
}
|
@ -5,6 +5,8 @@ all:
|
||||
# @-$(MAKE) /nologo /s /f makefile.mak $@
|
||||
@cd ..\doat
|
||||
@-$(MAKE) /nologo /s /f makefile.mak $@
|
||||
@cd ..\fishlim
|
||||
@-$(MAKE) /nologo /s /f makefile.mak $@
|
||||
@cd ..\lua
|
||||
@-$(MAKE) /nologo /s /f makefile.mak $@
|
||||
@cd ..\mpcinfo
|
||||
@ -29,6 +31,8 @@ clean:
|
||||
# @-$(MAKE) /nologo /s /f makefile.mak clean $@
|
||||
@cd ..\doat
|
||||
@-$(MAKE) /nologo /s /f makefile.mak clean $@
|
||||
@cd ..\fishlim
|
||||
@-$(MAKE) /nologo /s /f makefile.mak clean $@
|
||||
@cd ..\lua
|
||||
@-$(MAKE) /nologo /s /f makefile.mak clean $@
|
||||
@cd ..\mpcinfo
|
||||
|
Loading…
Reference in New Issue
Block a user