Line 0
Link Here
|
|
|
1 |
|
2 |
#ifdef HAVE_CONFIG_H |
3 |
#include "config.h" |
4 |
#endif |
5 |
|
6 |
#include <stdio.h> |
7 |
#include <string.h> |
8 |
|
9 |
#include "licq_file.h" |
10 |
#include "licq_gpg.h" |
11 |
#include "licq_log.h" |
12 |
|
13 |
CGPGHelper gGPGHelper; |
14 |
|
15 |
const char CGPGHelper::pgpSig[] = "-----BEGIN PGP MESSAGE-----"; |
16 |
|
17 |
|
18 |
CGPGHelper::CGPGHelper() |
19 |
: mKeysIni(INI_FxALLOWxCREATE) |
20 |
{ |
21 |
mCtx = 0; |
22 |
mGPGPassphrase = 0; |
23 |
} |
24 |
|
25 |
|
26 |
CGPGHelper::~CGPGHelper() |
27 |
{ |
28 |
if (mCtx) gpgme_release(mCtx); |
29 |
if (mGPGPassphrase) free(mGPGPassphrase); |
30 |
mKeysIni.CloseFile(); |
31 |
} |
32 |
|
33 |
|
34 |
char *CGPGHelper::Decrypt(const char *szCipher) |
35 |
{ |
36 |
if (!mCtx) return 0; |
37 |
|
38 |
size_t nRead = 0; |
39 |
GpgmeData cipher, plain; |
40 |
|
41 |
CGPGMEMutex mutex; |
42 |
if (!mutex.Lock()) return 0; |
43 |
if (gpgme_data_new(&cipher) != GPGME_No_Error) return 0; |
44 |
char *buf = strdup(szCipher); |
45 |
GpgmeError err; |
46 |
gpgme_data_write(cipher, buf, strlen(buf)); |
47 |
free(buf); |
48 |
if (gpgme_data_new(&plain) != GPGME_No_Error) { |
49 |
gpgme_data_release(cipher); |
50 |
return 0; |
51 |
} |
52 |
if ((err = gpgme_op_decrypt(mCtx, cipher, plain)) != GPGME_No_Error) |
53 |
gLog.Warn("%sgpgme message decryption failed: %s\n", L_WARNxSTR, gpgme_strerror(err)); |
54 |
gpgme_data_release(cipher); |
55 |
buf = gpgme_data_release_and_get_mem(plain, &nRead); |
56 |
if (!buf) return 0; |
57 |
buf = (char *)realloc(buf, nRead+1); |
58 |
buf[nRead] = 0; |
59 |
return buf; |
60 |
} |
61 |
|
62 |
|
63 |
char *CGPGHelper::Encrypt(const char *szPlain, unsigned long uin) |
64 |
{ |
65 |
if (!mCtx) return 0; |
66 |
if (!szPlain) return 0; |
67 |
|
68 |
gLog.Info("gpgme: Encrypting message to %lu\n", uin); |
69 |
|
70 |
char szUIN[20], buf[MAX_LINE_LEN]; |
71 |
mKeysIni.SetSection("keys"); |
72 |
snprintf(szUIN, 20, "%lu", uin); |
73 |
if (!mKeysIni.ReadStr(szUIN, buf)) return 0; |
74 |
|
75 |
CGPGMEMutex mutex; |
76 |
if (!mutex.Lock()) return 0; |
77 |
GpgmeRecipients rcps; |
78 |
GpgmeData plain = 0, cipher = 0; |
79 |
GpgmeError err; |
80 |
char *szCipher = 0; |
81 |
|
82 |
if (gpgme_recipients_new(&rcps) != GPGME_No_Error) return 0; |
83 |
if (gpgme_recipients_add_name_with_validity(rcps, buf, GPGME_VALIDITY_FULL) != GPGME_No_Error) |
84 |
gLog.Error("%sCouldn't use gpgme recipient: %s\n", L_ERRORxSTR, buf); |
85 |
else { |
86 |
if (gpgme_data_new_from_mem(&plain, szPlain, strlen(szPlain), 1) == GPGME_No_Error && |
87 |
gpgme_data_new(&cipher) == GPGME_No_Error) |
88 |
{ |
89 |
if ((err = gpgme_op_encrypt(mCtx, rcps, plain, cipher)) == GPGME_No_Error) { |
90 |
size_t nRead; |
91 |
if (gpgme_data_read(cipher, 0, 0, &nRead) == GPGME_No_Error) { |
92 |
szCipher = (char *)malloc(nRead+1); |
93 |
memset(szCipher, 0, nRead+1); |
94 |
gpgme_data_read(cipher, szCipher, nRead, &nRead); |
95 |
} |
96 |
} else |
97 |
gLog.Error("%sEncryption failed: %s\n", L_ERRORxSTR, gpgme_strerror(err)); |
98 |
} |
99 |
if (cipher) gpgme_data_release(cipher); |
100 |
if (plain) gpgme_data_release(plain); |
101 |
} |
102 |
gpgme_recipients_release(rcps); |
103 |
return szCipher; |
104 |
} |
105 |
|
106 |
|
107 |
void CGPGHelper::Start() |
108 |
{ |
109 |
char buf[MAX_LINE_LEN]; |
110 |
snprintf(buf, MAX_LINE_LEN, "%s/licq_gpg.conf", BASE_DIR); |
111 |
mKeysIni.LoadFile(buf); |
112 |
|
113 |
mKeysIni.SetSection("gpg"); |
114 |
mKeysIni.ReadStr("passphrase", buf); mGPGPassphrase = strdup(buf); |
115 |
|
116 |
const char *gpgme_ver = gpgme_check_version(0); |
117 |
gLog.Info("%sgpgme library found: %s\n", L_INITxSTR, gpgme_ver); |
118 |
|
119 |
if (gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP) != GPGME_No_Error) |
120 |
gLog.Error("%sgpgme engine OpenPGP not found!\n", L_ERRORxSTR); |
121 |
|
122 |
gpgme_new(&mCtx); |
123 |
gpgme_set_protocol(mCtx, GPGME_PROTOCOL_OpenPGP); |
124 |
gpgme_set_armor(mCtx, 1); |
125 |
gpgme_set_passphrase_cb(mCtx, PassphraseCallback, 0); |
126 |
} |
127 |
|
128 |
|
129 |
const char *CGPGHelper::PassphraseCallback(void *, const char *, void **) |
130 |
{ |
131 |
return gGPGHelper.mGPGPassphrase; |
132 |
} |
133 |
|
134 |
|
135 |
|
136 |
/*** GPGME lock for thread safety ***/ |
137 |
|
138 |
pthread_mutex_t CGPGMEMutex::mutex; |
139 |
|
140 |
CGPGMEMutex::~CGPGMEMutex() |
141 |
{ |
142 |
pthread_mutex_unlock(&mutex); |
143 |
} |
144 |
|
145 |
CGPGMEMutex::CGPGMEMutex() |
146 |
{ |
147 |
pthread_mutex_init(&mutex, 0); |
148 |
} |
149 |
|
150 |
bool CGPGMEMutex::Lock() |
151 |
{ |
152 |
return pthread_mutex_lock(&mutex) == 0; |
153 |
} |
154 |
|