7 #include "icqcontacts.h"
8 #include "abstracthook.h"
12 protocolname
impgp::opname
;
13 string
impgp::passphrase
[];
16 gpgme_check_version(NULL
);
26 string
impgp::getkeyinfo(const string
&fp
, bool secret
) {
30 if(ctx
&& !gpgme_get_key(ctx
, fp
.c_str(), &key
, secret
? 1 : 0)) {
31 r
= key
->subkeys
->keyid
+8;
35 if(key
->uids
->comment
&& strlen(key
->uids
->comment
))
36 r
+= (string
) " (" + key
->uids
->comment
+ ")";
38 if(key
->uids
->email
&& strlen(key
->uids
->email
))
39 r
+= (string
) " <" + key
->uids
->email
+ ">";
41 gpgme_key_release(key
);
47 vector
<string
> impgp::getkeys(bool secretonly
) {
52 gpgme_set_protocol(ctx
, GPGME_PROTOCOL_OpenPGP
);
54 if(!gpgme_op_keylist_start(ctx
, 0, secretonly
? 1 : 0)) {
55 while(!gpgme_op_keylist_next(ctx
, &key
)) {
56 r
.push_back(key
->subkeys
->keyid
);
57 gpgme_key_release(key
);
65 gpgme_error_t
impgp::passphrase_cb(void *hook
, const char *uidhint
,
66 const char *info
, int prevbad
, int fd
) {
69 if(passphrase
[opname
].empty())
70 passphrase
[opname
] = conf
->getourid(opname
).additional
["pgppass"];
72 if(passphrase
[opname
].empty())
73 passphrase
[opname
] = face
.inputstr(_("PGP passphrase required: "), "", '*');
76 face
.log((string
) "+ [" + conf
->getprotocolname(opname
) + "] " + _("incorrect PGP passphrase"));
77 // gethook(opname).disconnect(); // sudden disconnect isn't good for Jabber
78 return GPG_ERR_CANCELED
;
81 write(fd
, passphrase
[opname
].c_str(), passphrase
[opname
].size());
87 string
impgp::sign(const string
&text
, const string
&keyid
, protocolname pname
) {
95 gpgme_set_protocol(ctx
, GPGME_PROTOCOL_OpenPGP
);
96 gpgme_set_textmode(ctx
, 0);
97 gpgme_set_armor(ctx
, 1);
98 gpgme_set_passphrase_cb(ctx
, &passphrase_cb
, 0);
101 if(!(err
= gpgme_get_key(ctx
, keyid
.c_str(), &key
, 1))) {
102 gpgme_signers_clear(ctx
);
103 gpgme_signers_add(ctx
, key
);
105 if(!(err
= gpgme_data_new_from_mem(&in
, text
.c_str(), text
.size(), 0))) {
106 if(!(err
= gpgme_data_new(&out
))) {
107 if(!(err
= gpgme_op_sign(ctx
, in
, out
, GPGME_SIG_MODE_DETACH
))) {
108 auto_ptr
<char> buf(gpgme_data_release_and_get_mem(out
, &n
));
109 auto_ptr
<char> p(new char[n
+1]);
110 strncpy(p
.get(), buf
.get(), n
);
115 gpgme_data_release(out
);
119 gpgme_data_release(in
);
122 gpgme_key_release(key
);
125 if(err
&& err
!= GPG_ERR_CANCELED
) {
126 face
.log((string
) "+ [" + conf
->getprotocolname(pname
) + "] " +
127 _("PGP sign error: ") + gpgme_strerror(err
));
128 // gethook(pname).disconnect(); // sudden disconnect isn't good for Jabber
135 string
impgp::verify(string sign
, const string
&orig
) {
137 gpgme_data_t dsign
, dorig
;
139 gpgme_verify_result_t vr
;
142 sign
= "-----BEGIN PGP SIGNATURE-----\n\n" + sign
+ "\n-----END PGP SIGNATURE-----\n";
144 if(!gpgme_data_new_from_mem(&dsign
, sign
.c_str(), sign
.size(), 0)) {
145 if(!gpgme_data_new_from_mem(&dorig
, orig
.c_str(), orig
.size(), 0)) {
146 if(!gpgme_op_verify(ctx
, dsign
, dorig
, 0)) {
147 if(vr
= gpgme_op_verify_result(ctx
)) {
149 r
= vr
->signatures
->fpr
;
151 if(!gpgme_get_key(ctx
, r
.c_str(), &key
, 0)) {
152 r
= key
->subkeys
->keyid
;
153 gpgme_key_release(key
);
158 gpgme_data_release(dorig
);
160 gpgme_data_release(dsign
);
167 string
impgp::decrypt(string text
, protocolname pname
) {
169 gpgme_data_t in
, out
;
171 gpgme_decrypt_result_t dr
;
175 text
= "-----BEGIN PGP MESSAGE-----\n\n" + text
+ "\n-----END PGP MESSAGE-----\n";
176 gpgme_set_passphrase_cb(ctx
, &passphrase_cb
, 0);
179 if(!gpgme_data_new_from_mem(&in
, text
.c_str(), text
.size(), 0)) {
180 if(!gpgme_data_new(&out
)) {
181 if(!gpgme_op_decrypt(ctx
, in
, out
)) {
182 if(dr
= gpgme_op_decrypt_result(ctx
)) {
185 auto_ptr
<char> buf(gpgme_data_release_and_get_mem(out
, &n
));
186 auto_ptr
<char> p(new char[n
+1]);
187 strncpy(p
.get(), buf
.get(), n
);
191 gpgme_data_release(out
);
194 gpgme_data_release(in
);
201 string
impgp::encrypt(const string
&text
, const string
&keyid
, protocolname pname
) {
204 gpgme_data_t in
, out
;
209 gpgme_set_protocol(ctx
, GPGME_PROTOCOL_OpenPGP
);
210 gpgme_set_textmode(ctx
, 0);
211 gpgme_set_armor(ctx
, 1);
213 if(!(err
= gpgme_get_key(ctx
, keyid
.c_str(), &key
, 0))) {
214 gpgme_key_t keys
[] = { key
, 0 };
216 if(!(err
= gpgme_data_new_from_mem(&in
, text
.c_str(), text
.size(), 0))) {
217 if(!(err
= gpgme_data_new(&out
))) {
218 if(!(err
= gpgme_op_encrypt(ctx
, keys
, GPGME_ENCRYPT_ALWAYS_TRUST
, in
, out
))) {
219 auto_ptr
<char> p(gpgme_data_release_and_get_mem(out
, &n
));
223 gpgme_data_release(out
);
226 gpgme_data_release(in
);
228 gpgme_key_release(key
);
232 if(err
&& err
!= GPG_ERR_CANCELED
) {
233 face
.log((string
) "+ [" + conf
->getprotocolname(pname
) + "] " +
234 _("PGP encrypt error: ") + gpgme_strerror(err
));
235 gethook(pname
).disconnect();
241 bool impgp::havekey(const string
&keyid
) const {
243 bool r
= !gpgme_get_key(ctx
, keyid
.c_str(), &key
, 0);
244 if(r
) gpgme_key_release(key
);
248 bool impgp::enabled(protocolname pname
) const {
249 return gethook(pname
).getCapabs().count(hookcapab::pgp
)
250 && !conf
->getourid(pname
).additional
["pgpkey"].empty();
253 bool impgp::enabled(const imcontact
&ic
) const {
257 if(c
= clist
.get(ic
))
258 r
= enabled(ic
.pname
)
260 && !c
->getpgpkey().empty()
261 && havekey(c
->getpgpkey());
266 void impgp::clearphrase(protocolname p
) {
270 void impgp::strip(string
&r
) {
273 if((n
= r
.find("\n\n")) != -1)
276 if((n
= r
.rfind("\n")) != -1)
279 if((n
= r
.rfind("\n")) != -1)