00001
00002
00003 #include <sysdep.h>
00004 #include "include/libjwgc.h"
00005 #ifdef USE_GPGME
00006 #include <gpgme.h>
00007
00008 xode *key_list = NULL;
00009 int num_keys = 0;
00010
00011 static void
00012 print_op_info (GpgmeCtx c)
00013 {
00014 char *s = gpgme_get_op_info (c, 0);
00015
00016 if (!s) {
00017 dprintf(dGPG, "<!-- no operation info available -->");
00018 }
00019 else {
00020 dprintf(dGPG, "%s", s);
00021 free (s);
00022 }
00023 }
00024
00025 static const char *
00026 passphrase_cb (void *opaque, const char *desc, void **r_hd)
00027 {
00028 const char *pass;
00029
00030 if (!desc) {
00031 return NULL;
00032 }
00033
00034 pass = (char *)jVars_get(jVarGPGPass);
00035 return pass;
00036 }
00037
00038 char *
00039 JSign(char *data)
00040 {
00041 GpgmeCtx ctx;
00042 GpgmeError err;
00043 GpgmeData in, out;
00044 char *retdata;
00045 char buf[100];
00046 size_t nread;
00047 size_t retsz;
00048
00049 retdata = (char *)malloc(sizeof(char) * 1);
00050 retdata[0] = '\0';
00051 retsz = 0;
00052
00053 err = gpgme_new(&ctx);
00054 if (err) {
00055 dprintf(dGPG, "Failed to create GPGME context.\n");
00056 return NULL;
00057 }
00058
00059 gpgme_set_passphrase_cb(ctx, passphrase_cb, NULL);
00060 gpgme_set_textmode(ctx, 1);
00061 gpgme_set_armor(ctx, 1);
00062
00063 err = gpgme_data_new_from_mem(&in, data, strlen(data), 0);
00064 if (err) {
00065 dprintf(dGPG, "Failed to create input data.\n");
00066 return NULL;
00067 }
00068
00069 err = gpgme_data_new(&out);
00070 if (err) {
00071 dprintf(dGPG, "Failed to create output data.\n");
00072 return NULL;
00073 }
00074
00075 err = gpgme_op_sign(ctx, in, out, GPGME_SIG_MODE_DETACH);
00076 if (err) {
00077 dprintf(dGPG, "Detached signature failed.\n");
00078 return NULL;
00079 }
00080
00081 fflush(NULL);
00082 print_op_info(ctx);
00083
00084 err = gpgme_data_rewind(out);
00085 if (err) {
00086 dprintf(dGPG, "Failed to rewind data stream.\n");
00087 return NULL;
00088 }
00089 while (!(err = gpgme_data_read(out, buf, 100, &nread))) {
00090 retsz += nread;
00091 retdata = realloc(retdata, sizeof(char) * (retsz + 1));
00092 strcat(retdata, buf);
00093 retdata[retsz] = '\0';
00094 }
00095
00096 gpgme_data_release(out);
00097 gpgme_data_release(in);
00098 gpgme_release(ctx);
00099
00100 dprintf(dGPG, "Successfully signed data:\n%s\n", retdata);
00101
00102 return retdata;
00103 }
00104
00105 char *
00106 JTrimPGPMessage(char *msg)
00107 {
00108 char *retstr, *cp, *tmpbuf;
00109
00110 if (!msg) {
00111 dprintf(dGPG, "Trimming empty string.\n");
00112 return NULL;
00113 }
00114
00115 dprintf(dGPG, "Trimming:\n%s\n", msg);
00116
00117 retstr = (char *)malloc(sizeof(char) * 1);
00118 retstr[0] = '\0';
00119 tmpbuf = strdup(msg);
00120
00121 cp = tmpbuf;
00122 cp = strtok(cp, "\n");
00123 dprintf(dGPG, "Searching for BEGIN...\n", cp);
00124 while (cp && strncmp(cp, "-----BEGIN", 10)) {
00125 dprintf(dGPG, "Skipping %s\n", cp);
00126 cp = strtok(NULL, "\n");
00127 }
00128 if (!cp) { return NULL; }
00129 dprintf(dGPG, "Skipping %s\n", cp);
00130 cp = strtok(NULL, "\n");
00131 dprintf(dGPG, "Searching for end of headers...\n", cp);
00132 while (cp && !strchr(cp, ' ')) {
00133 dprintf(dGPG, "Skipping %s\n", cp);
00134 cp = strtok(NULL, "\n");
00135 }
00136 if (!cp) { return NULL; }
00137 dprintf(dGPG, "Skipping %s\n", cp);
00138 cp = strtok(NULL, "\n");
00139 dprintf(dGPG, "Collecting all until END...\n", cp);
00140 while (cp && strncmp(cp, "-----END", 8)) {
00141 dprintf(dGPG, "Keeping %s\n", cp);
00142 retstr = realloc(retstr, sizeof(char) * (strlen(retstr) +
00143 strlen(cp) + 2));
00144 strcat(retstr, cp);
00145 strcat(retstr, "\n");
00146 cp = strtok(NULL, "\n");
00147 }
00148 dprintf(dGPG, "Trimmed string is:\n%s\n", retstr);
00149
00150 return retstr;
00151 }
00152
00153 char *
00154 JDecrypt(char *data)
00155 {
00156 GpgmeCtx ctx;
00157 GpgmeError err;
00158 GpgmeData in, out;
00159 char *retdata;
00160 char *bufdata;
00161 char buf[100];
00162 size_t nread;
00163 size_t retsz;
00164
00165 retdata = (char *)malloc(sizeof(char) * 1);
00166 retdata[0] = '\0';
00167 retsz = 0;
00168
00169 err = gpgme_new(&ctx);
00170 if (err) {
00171 dprintf(dGPG, "Failed to create GPGME context.\n");
00172 return NULL;
00173 }
00174
00175 gpgme_set_passphrase_cb(ctx, passphrase_cb, NULL);
00176 gpgme_set_textmode(ctx, 1);
00177 gpgme_set_armor(ctx, 1);
00178
00179 bufdata = (char *)malloc(sizeof(char) * (strlen(data) + 1 + 68));
00180 sprintf(bufdata, "-----BEGIN PGP MESSAGE-----\nVersion: JWGC\n\n%s\n-----END PGP MESSAGE-----\n", data);
00181 dprintf(dGPG, "Parsing input data:\n%s\n", bufdata);
00182 err = gpgme_data_new_from_mem(&in, bufdata, strlen(bufdata), 0);
00183 if (err) {
00184 dprintf(dGPG, "Failed to create input data.\n");
00185 return NULL;
00186 }
00187
00188 err = gpgme_data_new(&out);
00189 if (err) {
00190 dprintf(dGPG, "Failed to create output data.\n");
00191 return NULL;
00192 }
00193
00194 err = gpgme_op_decrypt(ctx, in, out);
00195 if (err) {
00196 dprintf(dGPG, "Data decryption failed.\n");
00197 return NULL;
00198 }
00199
00200 fflush(NULL);
00201
00202 err = gpgme_data_rewind(out);
00203 if (err) {
00204 dprintf(dGPG, "Failed to rewind data stream.\n");
00205 return NULL;
00206 }
00207 while (!(err = gpgme_data_read(out, buf, 100, &nread))) {
00208 retsz += nread;
00209 retdata = realloc(retdata, sizeof(char) * (retsz + 1));
00210 strcat(retdata, buf);
00211 retdata[retsz] = '\0';
00212 }
00213
00214 gpgme_data_release(out);
00215 gpgme_data_release(in);
00216 gpgme_release(ctx);
00217
00218 dprintf(dGPG, "Successfully decrypted data:\n%s\n", retdata);
00219
00220 return retdata;
00221 }
00222
00223 char *
00224 JEncrypt(char *data, char *recipient)
00225 {
00226 GpgmeCtx ctx;
00227 GpgmeError err;
00228 GpgmeData in, out;
00229 GpgmeRecipients rset;
00230 char *retdata;
00231 char *bufdata;
00232 char buf[100];
00233 size_t nread;
00234 size_t retsz;
00235
00236 retdata = (char *)malloc(sizeof(char) * 1);
00237 retdata[0] = '\0';
00238 retsz = 0;
00239
00240 err = gpgme_check_engine();
00241 if (err) {
00242 dprintf(dGPG, "Failed to check GPG engine.\n");
00243 return NULL;
00244 }
00245 dprintf(dGPG, "Engine Info:\n%s\n", gpgme_get_engine_info());
00246
00247 err = gpgme_new(&ctx);
00248 if (err) {
00249 dprintf(dGPG, "Failed to create GPGME context.\n");
00250 return NULL;
00251 }
00252
00253 gpgme_set_armor(ctx, 1);
00254
00255 err = gpgme_data_new_from_mem(&in, data, strlen(data), 0);
00256 if (err) {
00257 dprintf(dGPG, "Failed to create input data.\n");
00258 return NULL;
00259 }
00260
00261 err = gpgme_data_new(&out);
00262 if (err) {
00263 dprintf(dGPG, "Failed to create output data.\n");
00264 return NULL;
00265 }
00266
00267 err = gpgme_recipients_new(&rset);
00268 if (err) {
00269 dprintf(dGPG, "Failed to initialize recipients.\n");
00270 return NULL;
00271 }
00272
00273 err = gpgme_recipients_add_name_with_validity(rset, recipient,
00274 GPGME_VALIDITY_FULL);
00275 if (err) {
00276 dprintf(dGPG, "Failed to add recipient.\n");
00277 return NULL;
00278 }
00279
00280 err = gpgme_op_encrypt(ctx, rset, in, out);
00281 if (err) {
00282 dprintf(dGPG, "Data encryption failed.\n");
00283 return NULL;
00284 }
00285
00286 print_op_info(ctx);
00287 fflush(NULL);
00288
00289 err = gpgme_data_rewind(out);
00290 if (err) {
00291 dprintf(dGPG, "Failed to rewind data stream.\n");
00292 return NULL;
00293 }
00294 while (!(err = gpgme_data_read(out, buf, 100, &nread))) {
00295 retsz += nread;
00296 retdata = realloc(retdata, sizeof(char) * (retsz + 1));
00297 strcat(retdata, buf);
00298 retdata[retsz] = '\0';
00299 }
00300
00301 gpgme_recipients_release(rset);
00302 gpgme_data_release(out);
00303 gpgme_data_release(in);
00304 gpgme_release(ctx);
00305
00306 dprintf(dGPG, "Successfully encrypted data:\n%s\n", retdata);
00307
00308 return retdata;
00309 }
00310
00311 static const char *
00312 status_string(GpgmeSigStat status)
00313 {
00314 const char *s = "?";
00315
00316 switch (status) {
00317 case GPGME_SIG_STAT_NONE:
00318 s = "None";
00319 break;
00320
00321 case GPGME_SIG_STAT_NOSIG:
00322 s = "No Signature";
00323 break;
00324
00325 case GPGME_SIG_STAT_GOOD:
00326 s = "Good";
00327 break;
00328
00329 case GPGME_SIG_STAT_GOOD_EXP:
00330 s = "Good but expired";
00331 break;
00332
00333 case GPGME_SIG_STAT_GOOD_EXPKEY:
00334 s = "Good but key exipired";
00335 break;
00336
00337 case GPGME_SIG_STAT_BAD:
00338 s = "Bad";
00339 break;
00340
00341 case GPGME_SIG_STAT_NOKEY:
00342 s = "No Key";
00343 break;
00344
00345 case GPGME_SIG_STAT_ERROR:
00346 s = "Error";
00347 break;
00348
00349 case GPGME_SIG_STAT_DIFF:
00350 s = "More than one signature";
00351 break;
00352 }
00353 return s;
00354 }
00355
00356 static const char *
00357 validity_string(GpgmeValidity val)
00358 {
00359 const char *s = "?";
00360
00361 switch (val) {
00362 case GPGME_VALIDITY_UNKNOWN:
00363 s = "unknown";
00364 break;
00365
00366 case GPGME_VALIDITY_NEVER:
00367 s = "not trusted";
00368 break;
00369
00370 case GPGME_VALIDITY_MARGINAL:
00371 s = "marginal trusted";
00372 break;
00373
00374 case GPGME_VALIDITY_FULL:
00375 s = "fully trusted";
00376 break;
00377
00378 case GPGME_VALIDITY_UNDEFINED:
00379 case GPGME_VALIDITY_ULTIMATE:
00380 break;
00381 }
00382 return s;
00383 }
00384
00385 static void
00386 print_sig_stat(GpgmeCtx ctx, GpgmeSigStat status)
00387 {
00388 const char *s;
00389 time_t created;
00390 int idx;
00391 GpgmeKey key;
00392
00393 dprintf(dGPG, "Verification Status: %s\n", status_string(status));
00394
00395 for(idx=0; (s=gpgme_get_sig_status(ctx, idx, &status, &created));
00396 idx++) {
00397 dprintf(dGPG, "sig %d: created: %lu expires: %lu status: %s\n",
00398 idx, (unsigned long)created,
00399 gpgme_get_sig_ulong_attr(ctx, idx, GPGME_ATTR_EXPIRE,0),
00400 status_string(status));
00401 dprintf(dGPG, "sig %d: fpr/keyid: `%s' validity: %s\n",
00402 idx, s,
00403 validity_string(gpgme_get_sig_ulong_attr
00404 (ctx, idx, GPGME_ATTR_VALIDITY, 0)));
00405 if (!gpgme_get_sig_key(ctx, idx, &key)) {
00406 char *p = gpgme_key_get_as_xml(key);
00407 dprintf(dGPG, "sig %d: key object:\n%s\n", idx, p);
00408 free(p);
00409 gpgme_key_release(key);
00410 }
00411 }
00412 }
00413
00414
00415 char *
00416 JGetSignature(char *text, char *sig)
00417 {
00418 GpgmeCtx ctx;
00419 GpgmeError err;
00420 GpgmeData gsig, gtext;
00421 GpgmeSigStat status;
00422 char *retdata;
00423 char *sigdata;
00424 char buf[100];
00425 size_t nread;
00426 size_t retsz;
00427 time_t created;
00428 int idx;
00429 const char *s;
00430
00431 retdata = strdup("");
00432 retsz = 0;
00433
00434 err = gpgme_new(&ctx);
00435 if (err) {
00436 dprintf(dGPG, "Failed to create GPGME context.\n");
00437 return NULL;
00438 }
00439
00440 err = gpgme_data_new_from_mem(>ext, text, strlen(text), 0);
00441 if (err) {
00442 dprintf(dGPG, "Failed to create text data.\n");
00443 return NULL;
00444 }
00445
00446 sigdata = (char *)malloc(sizeof(char) * (strlen(sig) + 1 + 72));
00447 sprintf(sigdata, "-----BEGIN PGP SIGNATURE-----\nVersion: JWGC\n\n%s\n-----END PGP SIGNATURE-----\n", sig);
00448 dprintf(dGPG, "Parsing input data:\n%s\n", sigdata);
00449 err = gpgme_data_new_from_mem(&gsig, sigdata, strlen(sigdata), 0);
00450 if (err) {
00451 dprintf(dGPG, "Failed to create sig data.\n");
00452 return NULL;
00453 }
00454
00455 err = gpgme_op_verify(ctx, gsig, gtext, &status);
00456 if (err) {
00457 dprintf(dGPG, "Data verification failed.\n");
00458 return NULL;
00459 }
00460
00461 print_sig_stat(ctx, status);
00462
00463 fflush(NULL);
00464
00465 idx = 0;
00466 s = gpgme_get_sig_status(ctx, idx, &status, &created);
00467 if (!s) {
00468 dprintf(dGPG, "Unable to determine signature.\n");
00469 return NULL;
00470 }
00471 retdata = strdup(s);
00472
00473 gpgme_data_release(gsig);
00474 gpgme_data_release(gtext);
00475 gpgme_release(ctx);
00476
00477 dprintf(dGPG, "Successfully verified signature:\n%s\n", retdata);
00478
00479 return retdata;
00480 }
00481
00482 void
00483 insert_into_key_list(char *jid, char *key)
00484 {
00485 int i, k;
00486 xode s;
00487
00488 num_keys++;
00489 key_list = realloc(key_list, sizeof(xode) * (num_keys));
00490 key_list[num_keys - 1] = malloc(sizeof(xode));
00491
00492 for (i = 0; i < (num_keys - 1) &&
00493 (strcasecmp(jid, xode_get_attrib(key_list[i], "jid")) > 0);
00494 i++);
00495
00496 for (k = (num_keys - 1); k > i; k--) {
00497 key_list[k] = key_list[k - 1];
00498 }
00499
00500 key_list[k] = xode_new("key");
00501 xode_put_attrib(key_list[k], "jid", jid);
00502 xode_put_attrib(key_list[k], "id", key);
00503 }
00504
00505 void
00506 JUpdateKeyList(char *jid, char *textstring, char *sigstring)
00507 {
00508 int i;
00509 char *key;
00510
00511 key = JGetSignature(textstring, sigstring);
00512 if (!key) {
00513 dprintf(dGPG, "No valid key returned, skipping.\n");
00514 return;
00515 }
00516
00517 dprintf(dGPG, "KeyID is %s\n", key);
00518
00519 for (i = 0; i < num_keys; i++) {
00520 if (!strcasecmp(xode_get_attrib(key_list[i], "jid"), jid)) {
00521 xode_hide_attrib(key_list[i], "id");
00522 xode_put_attrib(key_list[i], "id", key);
00523 return;
00524 }
00525 }
00526
00527 insert_into_key_list(jid, key);
00528 }
00529
00530 char *
00531 JGetKeyID(char *jid)
00532 {
00533 int i;
00534 char *key;
00535
00536 for (i = 0; i < num_keys; i++) {
00537 if (!strcasecmp(xode_get_attrib(key_list[i], "jid"), jid)) {
00538 key = xode_get_attrib(key_list[i], "id");
00539 return key;
00540 }
00541 }
00542
00543 return NULL;
00544 }
00545 #endif