/* The main GPG decryption routine for libfko. */ int gpgme_decrypt(fko_ctx_t fko_ctx, unsigned char *indata, size_t in_len, const char *pw, unsigned char **out, size_t *out_len) { char *tmp_buf; int res; gpgme_ctx_t gpg_ctx = NULL; gpgme_data_t cipher = NULL; gpgme_data_t plaintext = NULL; gpgme_error_t err; gpgme_decrypt_result_t decrypt_res; gpgme_verify_result_t verify_res; /* Initialize gpgme */ res = init_gpgme(fko_ctx); if(res != FKO_SUCCESS) return(res); gpg_ctx = fko_ctx->gpg_ctx; err = gpgme_data_new(&plaintext); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_PLAINTEXT_DATA_OBJ); } /* Initialize the cipher data (place into gpgme_data object) */ err = gpgme_data_new_from_mem(&cipher, (char*)indata, in_len, 0); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_CIPHER_DATA_OBJ); } /* Set the passphrase callback. */ gpgme_set_passphrase_cb(gpg_ctx, my_passphrase_cb, (void*)pw); /* Now decrypt and verify. */ err = gpgme_op_decrypt_verify(gpg_ctx, cipher, plaintext); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_data_release(cipher); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_DECRYPT_FAILED); } /* Done with the cipher text. */ gpgme_data_release(cipher); /* We check the "usupported_algorithm" flag in the decrypt result. */ decrypt_res = gpgme_op_decrypt_result(gpg_ctx); if(decrypt_res->unsupported_algorithm) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; return(FKO_ERROR_GPGME_DECRYPT_UNSUPPORTED_ALGORITHM); } /* Now verify the signatures if so configured. */ if(fko_ctx->verify_gpg_sigs) { verify_res = gpgme_op_verify_result(gpg_ctx); res = process_sigs(fko_ctx, verify_res); if(res != FKO_SUCCESS) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; return(res); } } /* Get the encrypted data and its length from the gpgme data object. */ tmp_buf = gpgme_data_release_and_get_mem(plaintext, out_len); /* Use calloc here with an extra byte because I am not sure if all systems * will include the terminating NULL with the decrypted data (which is * expected to be a string). */ *out = calloc(1, *out_len+1); /* This is freed upon fko_ctx destruction. */ if(*out == NULL) res = FKO_ERROR_MEMORY_ALLOCATION; else { memcpy(*out, tmp_buf, *out_len); res = FKO_SUCCESS; } gpgme_free(tmp_buf); return(res); }
int main (int argc, char *argv[]) { DSPAM_CTX *CTX = NULL, *CTX2; char *user; int do_sigs = 0; int do_probs = 0; int do_unused = 0; int age_sigs = 14; int age_probs = 30; int age_unused[4] = { 90, 30, 15, 15 }; int i, help = 0; struct nt *users = NULL; struct nt_node *node = NULL; #ifndef _WIN32 #ifdef TRUSTED_USER_SECURITY struct passwd *p = getpwuid (getuid ()); #endif #endif /* Read dspam.conf */ agent_config = read_config(NULL); if (!agent_config) { LOG(LOG_ERR, ERR_AGENT_READ_CONFIG); fprintf (stderr, ERR_AGENT_READ_CONFIG "\n"); exit(EXIT_FAILURE); } if (!_ds_read_attribute(agent_config, "Home")) { LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME); fprintf (stderr, ERR_AGENT_DSPAM_HOME "\n"); goto bail; } if (libdspam_init(_ds_read_attribute(agent_config, "StorageDriver")) != 0) { LOG(LOG_ERR, ERR_DRV_INIT); fprintf (stderr, ERR_DRV_INIT "\n"); _ds_destroy_config(agent_config); exit(EXIT_FAILURE); } #ifndef _WIN32 #ifdef TRUSTED_USER_SECURITY if (!_ds_match_attribute(agent_config, "Trust", p->pw_name) && p->pw_uid) { fprintf(stderr, ERR_TRUSTED_MODE "\n"); goto bail; } #endif #endif for(i=0;i<argc;i++) { if (!strncmp (argv[i], "--profile=", 10)) { if (!_ds_match_attribute(agent_config, "Profile", argv[i]+10)) { LOG(LOG_ERR, ERR_AGENT_NO_SUCH_PROFILE, argv[i]+10); fprintf (stderr, ERR_AGENT_NO_SUCH_PROFILE "\n", argv[i]+10); goto bail; } else { _ds_overwrite_attribute(agent_config, "DefaultProfile", argv[i]+10); } break; } } #ifdef DEBUG fprintf (stdout, "dspam_clean starting\n"); #endif if (_ds_read_attribute(agent_config, "PurgeSignatures") && !_ds_match_attribute(agent_config, "PurgeSignatures", "off")) { do_sigs = 1; age_sigs = atoi(_ds_read_attribute(agent_config, "PurgeSignatures")); } if (_ds_read_attribute(agent_config, "PurgeNeutral") && !_ds_match_attribute(agent_config, "PurgeNeutral", "off")) { do_probs = 1; age_probs = atoi(_ds_read_attribute(agent_config, "PurgeNeutral")); } if (_ds_read_attribute(agent_config, "PurgeUnused") && !_ds_match_attribute(agent_config, "PurgeUnused", "off")) { int i; do_unused = 1; age_unused[0] = atoi(_ds_read_attribute(agent_config, "PurgeUnused")); age_unused[1] = atoi(_ds_read_attribute(agent_config, "PurgeHapaxes")); age_unused[2] = atoi(_ds_read_attribute(agent_config, "PurgeHits1S")); age_unused[3] = atoi(_ds_read_attribute(agent_config, "PurgeHits1I")); for(i=0;i<4;i++) if (age_unused[i]==0) do_unused = 0; } users = nt_create(NT_CHAR); if (users == NULL) { fprintf(stderr, "%s", ERR_MEM_ALLOC); goto bail; } for(i=0;i<argc;i++) { if (!strncmp(argv[i], "-p", 2)) { do_probs = 1; if (strlen(argv[i])>2) age_probs = atoi(argv[i]+2); } else if (!strncmp(argv[i], "-s", 2)) { do_sigs = 1; if (strlen(argv[i])>2) age_sigs = atoi(argv[i]+2); } else if (!strncmp(argv[i], "-u", 2)) { do_unused = 1; if (strlen(argv[i])>2) { char *c = strdup(argv[i]+2); char *d = strtok(c, ","); int j = 0; while(d != NULL && j<4) { age_unused[j] = atoi(d); j++; d = strtok(NULL, ","); } free(c); } } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) help = 1; else if (i>0) nt_add(users, argv[i]); } if (help || (!do_probs && !do_sigs && !do_unused)) { fprintf(stderr, "%s", CLEANSYNTAX); _ds_destroy_config(agent_config); nt_destroy(users); libdspam_shutdown(); if (help) { exit(EXIT_SUCCESS); } exit(EXIT_FAILURE); } open_ctx = open_mtx = NULL; signal (SIGINT, dieout); signal (SIGPIPE, dieout); signal (SIGTERM, dieout); dspam_init_driver (NULL); if (users->items == 0) { CTX = dspam_create (NULL, NULL, _ds_read_attribute(agent_config, "Home"), DSM_TOOLS, 0); open_ctx = CTX; if (CTX == NULL) { fprintf (stderr, "Could not initialize context: %s\n", strerror (errno)); dspam_shutdown_driver (NULL); goto bail; } set_libdspam_attributes(CTX); if (dspam_attach(CTX, NULL)) { LOG (LOG_WARNING, "unable to attach dspam context"); fprintf (stderr, "Unable to attach DSPAM context\n"); goto bail; } user = _ds_get_nextuser (CTX); } else { node = users->first; if (node != NULL) user = node->ptr; else goto bail; } while (user != NULL) { #ifdef DEBUG printf ("PROCESSING USER: %s\n", user); #endif CTX2 = dspam_create (user, NULL, _ds_read_attribute(agent_config, "Home"), DSM_TOOLS, 0); open_mtx = CTX2; if (CTX2 == NULL) { fprintf (stderr, "Could not initialize context: %s\n", strerror (errno)); return EUNKNOWN; } set_libdspam_attributes(CTX2); if (dspam_attach(CTX2, NULL)) { LOG (LOG_WARNING, "unable to attach dspam context"); fprintf (stderr, "Unable to attach DSPAM context\n"); goto bail; } if (do_sigs) process_sigs(CTX2, age_sigs); if (do_probs) process_probs(CTX2, age_probs); if (do_unused) process_unused(CTX2, age_unused[0], age_unused[1], age_unused[2], age_unused[3]); dspam_destroy (CTX2); open_mtx = NULL; if (users->items == 0) { user = _ds_get_nextuser (CTX); } else { if (node == NULL || node->next == NULL) { node = NULL; user = NULL; } else { node = node->next; user = node->ptr; } } } if (users->items == 0) { dspam_destroy (CTX); open_ctx = NULL; } dspam_shutdown_driver (NULL); _ds_destroy_config(agent_config); nt_destroy(users); libdspam_shutdown(); exit (EXIT_SUCCESS); bail: if (open_ctx) dspam_destroy(open_ctx); if (open_mtx) dspam_destroy(open_mtx); _ds_destroy_config(agent_config); nt_destroy(users); libdspam_shutdown(); exit(EXIT_FAILURE); }