Пример #1
0
static GString *purple_fbapi_construct_request_vargs(PurpleAccount *account, const char *method, va_list args)
{
	GTree *params;
	const char *api_key, *api_secret;
	const char *key, *value;
	char call_id[21];
	char *signature;
	GString *body;

	/* Read all paramters into a sorted tree */
	params = g_tree_new((GCompareFunc)strcmp);
	while ((key = va_arg(args, const char *)) != NULL)
	{
		value = va_arg(args, const char *);
		g_tree_insert(params, (char *)key, (char *)value);

		/* If we have a session_key then we need a call_id */
		if (g_str_equal(key, "session_key")) {
			struct timeval tv;
			if (gettimeofday(&tv, NULL) != 0) {
				time_t now;
				purple_debug_error("fbapi",
						"Error calling gettimeofday(): %s\n",
						g_strerror(errno));
				now = time(NULL);
				strftime(call_id, sizeof(call_id), "%s000000", localtime(&now));
			} else {
				char tmp[22];
				strftime(tmp, sizeof(tmp), "%s", localtime(&tv.tv_sec));
				sprintf(call_id, "%s%06lu", tmp, (long unsigned int)tv.tv_usec);
			}
			g_tree_insert(params, "call_id", call_id);
		}
	}

	api_key = purple_account_get_string(account, "fb_api_key", PURPLE_FBAPI_KEY);
	api_secret = purple_account_get_string(account, "fb_api_secret", API_SECRET);

	/* Add the method and api_key parameters to the list */
	g_tree_insert(params, "method", (char *)method);
	g_tree_insert(params, "api_key", (char *)api_key);

	/* Add the signature parameter to the list */
	signature = generate_signature((char *)api_secret, params);
	g_tree_insert(params, "sig", signature);

	/* Construct the body of the HTTP POST request */
	body = g_string_new(NULL);
	g_tree_foreach(params, append_params_to_body, body);
	g_tree_destroy(params);
	g_free(signature);

	return body;
}
// Add a signature at the end of every <file_info> element,
//
int add_signatures(char* xml, R_RSA_PRIVATE_KEY& key) {
    char* p = xml, *q1, *q2, buf[BLOB_SIZE], buf2[BLOB_SIZE];
    char signature_hex[BLOB_SIZE];
    char signature_xml[BLOB_SIZE];
    char signed_xml[1024];
    int retval, len;

    while (1) {
        q1 = strstr(p, "<file_info>\n");
        if (!q1) break;
        q2 = strstr(q1, "</file_info>");
        if (!q2) {
            fprintf(stderr, "add_signatures: malformed XML: %s\n", xml);
            return ERR_XML_PARSE;
        }

        q1 += strlen("<file_info>\n");
        len = q2 - q1;
        memcpy(buf, q1, len);
        buf[len] = 0;
        char name[1024];
        if (!parse_str(buf, "<name>", name, sizeof(name))) {
            fprintf(stderr, "add_signatures: missing name: %s", buf);
            return ERR_XML_PARSE;
        }
        double max_nbytes;
        if (!parse_double(buf, "<max_nbytes>", max_nbytes)) {
            fprintf(stderr, "add_signatures: missing max_nbytes: %s", buf);
            return ERR_XML_PARSE;
        }
        sprintf(signed_xml, "<name>%s</name><max_nbytes>%.0f</max_nbytes>",
            name, max_nbytes
        );
        retval = generate_signature(signed_xml, signature_hex, key);
        sprintf(signature_xml,
            "<xml_signature>\n%s</xml_signature>\n", signature_hex
        );
        if (retval) return retval;
        strcpy(buf2, q2);
        strcpy(q1, buf);
        strcat(q1, signature_xml);
        strcat(q1, buf2);
        p = q1;
    }
    return 0;
}
Пример #3
0
void fill_session_url(CMStringA &buf, CMStringA &token, CMStringA &secret, time_t &hosttime, const char *password, bool encryption)
{
	/*
		AIM_SESSION_URL?query_string?sig_sha256=signature
		*/

	CMStringA query_string;
	query_string.Format("a=%s&distId=%s&f=xml&k=%s&ts=%llu&useTLS=%d", token, AIM_DEFAULT_DISTID, AIM_DEFAULT_CLIENT_KEY, hosttime, (int)encryption);

	BYTE session_key[MIR_SHA256_HASH_SIZE], signature[MIR_SHA256_HASH_SIZE];
	mir_hmac_sha256(session_key, (BYTE*)password, mir_strlen(password), (BYTE*)secret.GetString(), secret.GetLength());

	ptrA szKey(mir_base64_encode(session_key, sizeof(session_key)));
	generate_signature(signature, "GET", AIM_SESSION_URL, query_string, szKey);

	ptrA szEncoded(mir_base64_encode(signature, sizeof(signature)));
	buf.Format("%s?%s&sig_sha256=%s", AIM_SESSION_URL, query_string, (char*)szEncoded);
}
Пример #4
0
static void send_start_oscar_session(OscarData *od, const char *token, const char *session_key, time_t hosttime)
{
    char *query_string, *signature, *url;
    PurpleAccount *account;
    gboolean use_tls;

    account = purple_connection_get_account(od->gc);
    use_tls = purple_account_get_bool(account, "use_ssl", OSCAR_DEFAULT_USE_SSL);

    /*
     * Construct the GET parameters.  0x00000611 is the distid given to
     * us by AOL for use as the default libpurple distid.
     */
    query_string = g_strdup_printf("a=%s"
                                   "&distId=%d"
                                   "&f=xml"
                                   "&k=%s"
                                   "&ts=%" PURPLE_TIME_T_MODIFIER
                                   "&useTLS=%d",
                                   purple_url_encode(token),
                                   oscar_get_ui_info_int(od->icq ? "prpl-icq-distid"
                                           : "prpl-aim-distid", 0x00000611),
                                   get_client_key(od), hosttime, use_tls);
    signature = generate_signature("GET", URL_START_OSCAR_SESSION,
                                   query_string, session_key);
    url = g_strdup_printf(URL_START_OSCAR_SESSION "?%s&sig_sha256=%s",
                          query_string, signature);
    g_free(query_string);
    g_free(signature);

    /* Make the request */
    od->url_data = purple_util_fetch_url_request_len_with_account(account,
                   url, TRUE, NULL, FALSE, NULL, FALSE, -1,
                   start_oscar_session_cb, od);
    g_free(url);
}
Пример #5
0
static void send_start_oscar_session(OscarData *od, const char *token, const char *session_key, time_t hosttime)
{
	char *query_string, *signature, *url;
	gboolean use_tls = purple_account_get_bool(purple_connection_get_account(od->gc), "use_ssl", OSCAR_DEFAULT_USE_SSL);

	/* Construct the GET parameters */
	query_string = g_strdup_printf("a=%s"
			"&f=xml"
			"&k=%s"
			"&ts=%" PURPLE_TIME_T_MODIFIER
			"&useTLS=%d",
			purple_url_encode(token), get_client_key(od), hosttime, use_tls);
	signature = generate_signature("GET", URL_START_OSCAR_SESSION,
			query_string, session_key);
	url = g_strdup_printf(URL_START_OSCAR_SESSION "?%s&sig_sha256=%s",
			query_string, signature);
	g_free(query_string);
	g_free(signature);

	/* Make the request */
	od->url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE,
			start_oscar_session_cb, od);
	g_free(url);
}
Пример #6
0
int main(int argc, char** argv) {
    R_RSA_PUBLIC_KEY public_key;
    R_RSA_PRIVATE_KEY private_key;
    int i, n, retval;
    bool is_valid;
    DATA_BLOCK signature, in, out;
    unsigned char signature_buf[256], buf[256], buf2[256];
    FILE *f, *fpriv, *fpub;
    char cbuf[256];
    RSA rsa_key;
    RSA *rsa_key_;
	BIO *bio_out=NULL;
    BIO *bio_err=NULL;
    char *certpath;
    bool b2o=false; // boinc key to openssl key ?
    bool kpriv=false; // private key ?

    if (argc == 1) {
        usage();
        exit(1);
    }
    if (!strcmp(argv[1], "-genkey")) {
        if (argc < 5) {
            usage();
            exit(1);
        }
        printf("creating keys in %s and %s\n", argv[3], argv[4]);
        n = atoi(argv[2]);

        srand(random_int());
        RSA* rp = RSA_generate_key(n,  65537, 0, 0);
        openssl_to_keys(rp, n, private_key, public_key);
        fpriv = fopen(argv[3], "w");
        if (!fpriv) die("fopen");
        fpub = fopen(argv[4], "w");
        if (!fpub) die("fopen");
        print_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key));
        print_key_hex(fpub, (KEY*)&public_key, sizeof(public_key));

    } else if (!strcmp(argv[1], "-sign")) {
        if (argc < 4) {
            usage();
            exit(1);
        }
        fpriv = fopen(argv[3], "r");
        if (!fpriv) die("fopen");
        retval = scan_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key));
        if (retval) die("scan_key_hex\n");
        signature.data = signature_buf;
        signature.len = 256;
        retval = sign_file(argv[2], private_key, signature);
        print_hex_data(stdout, signature);
    } else if (!strcmp(argv[1], "-sign_string")) {
        if (argc < 4) {
            usage();
            exit(1);
        }
        fpriv = fopen(argv[3], "r");
        if (!fpriv) die("fopen");
        retval = scan_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key));
        if (retval) die("scan_key_hex\n");
        generate_signature(argv[2], cbuf, private_key);
        puts(cbuf);
    } else if (!strcmp(argv[1], "-verify")) {
        if (argc < 5) {
            usage();
            exit(1);
        }
        fpub = fopen(argv[4], "r");
        if (!fpub) die("fopen");
        retval = scan_key_hex(fpub, (KEY*)&public_key, sizeof(public_key));
        if (retval) die("read_public_key");
        f = fopen(argv[3], "r");
        signature.data = signature_buf;
        signature.len = 256;
        retval = scan_hex_data(f, signature);
        if (retval) die("scan_hex_data");
        retval = verify_file(argv[2], public_key, signature, is_valid);
        if (retval) die("verify_file");
        if (is_valid) {
            printf("file is valid\n");
        } else {
            printf("file is invalid\n");
            return 1;
        }
    } else if (!strcmp(argv[1], "-test_crypt")) {
        if (argc < 4) {
            usage();
            exit(1);
        }
        fpriv = fopen(argv[2], "r");
        if (!fpriv) die("fopen");
        retval = scan_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key));
        if (retval) die("scan_key_hex\n");
        fpub = fopen(argv[3], "r");
        if (!fpub) die("fopen");
        retval = scan_key_hex(fpub, (KEY*)&public_key, sizeof(public_key));
        if (retval) die("read_public_key");
        strcpy((char*)buf2, "encryption test successful");
        in.data = buf2;
        in.len = strlen((char*)in.data);
        out.data = buf;
        encrypt_private(private_key, in, out);
        in = out;
        out.data = buf2;
        decrypt_public(public_key, in, out);
        printf("out: %s\n", out.data);
    } else if (!strcmp(argv[1], "-cert_verify")) {
        if (argc < 6)
            die("usage: crypt_prog -cert_verify file signature_file certificate_dir ca_dir \n");

        f = fopen(argv[3], "r");
        signature.data = signature_buf;
        signature.len = 256;
        retval = scan_hex_data(f, signature);
        if (retval) die("cannot scan_hex_data");
        certpath = check_validity(argv[4], argv[2], signature.data, argv[5]);
        if (certpath == NULL) {
            die("signature cannot be verfied.\n\n");
        } else {
            printf("siganture verified using certificate '%s'.\n\n", certpath);
            free(certpath);
        }
    // this converts, but an executable signed with sign_executable,
    // and signature converted to OpenSSL format cannot be verified with
    // OpenSSL
    } else if (!strcmp(argv[1], "-convsig")) {
        if (argc < 5) {
            usage();
            exit(1);
        }
        if (strcmp(argv[2], "b2o") == 0) {
            b2o = true;
        } else if (strcmp(argv[2], "o2b") == 0) {
            b2o = false;
        } else {
            die("either 'o2b' or 'b2o' must be defined for -convsig\n");
        }
        if (b2o) {
            f = fopen(argv[3], "r");
            signature.data = signature_buf;
            signature.len = 256;
            retval = scan_hex_data(f, signature);
            fclose(f);
            f = fopen(argv[4], "w+");
            print_raw_data(f, signature);
            fclose(f);
        } else {
            f = fopen(argv[3], "r");
            signature.data = signature_buf;
            signature.len = 256;
            retval = scan_raw_data(f, signature);
            fclose(f);
            f = fopen(argv[4], "w+");
            print_hex_data(f, signature);
            fclose(f);
        }
    } else if (!strcmp(argv[1], "-convkey")) {
        if (argc < 6) {
            usage();
            exit(1);
        }
        if (strcmp(argv[2], "b2o") == 0) {
            b2o = true;
        } else if (strcmp(argv[2], "o2b") == 0) {
            b2o = false;
        } else {
            die("either 'o2b' or 'b2o' must be defined for -convkey\n");
        }
        if (strcmp(argv[3], "pub") == 0) {
            kpriv = false;
        } else if (strcmp(argv[3], "priv") == 0)  {
            kpriv = true;
        } else {
            die("either 'pub' or 'priv' must be defined for -convkey\n");
        }
        OpenSSL_add_all_algorithms();
		ERR_load_crypto_strings();
		ENGINE_load_builtin_engines();
		if (bio_err == NULL) {
		    bio_err = BIO_new_fp(stdout, BIO_NOCLOSE);
        }
        //enc=EVP_get_cipherbyname("des");
        //if (enc == NULL)
        //    die("could not get cypher.\n");
        // no encription yet.
        bio_out=BIO_new(BIO_s_file());
		if (BIO_write_filename(bio_out,argv[5]) <= 0) {
			perror(argv[5]);
            die("could not create output file.\n");
        }
        if (b2o) {
            rsa_key_ = RSA_new();
            if (kpriv) {
                fpriv = fopen(argv[4], "r");
                if (!fpriv) {
                    die("fopen");
                }
                scan_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key));
                fclose(fpriv);
                private_to_openssl(private_key, &rsa_key);

                //i = PEM_write_bio_RSAPrivateKey(bio_out, &rsa_key,
        		//				enc, NULL, 0, pass_cb, NULL);
        		// no encryption yet.
        		
                //i = PEM_write_bio_RSAPrivateKey(bio_out, &rsa_key,
        		//				NULL, NULL, 0, pass_cb, NULL);
                fpriv = fopen(argv[5], "w+");
                PEM_write_RSAPrivateKey(fpriv, &rsa_key, NULL, NULL, 0, 0, NULL);
                fclose(fpriv);
    		    //if (i == 0) {
                //    ERR_print_errors(bio_err);
                //    die("could not write key file.\n");
    		    //}
            } else {
                fpub = fopen(argv[4], "r");
                if (!fpub) {
                    die("fopen");
                }
                scan_key_hex(fpub, (KEY*)&public_key, sizeof(public_key));
                fclose(fpub);
                fpub = fopen(argv[5], "w+");
                if (!fpub) {
                    die("fopen");
                }
                public_to_openssl(public_key, rsa_key_);
    		    i = PEM_write_RSA_PUBKEY(fpub, rsa_key_);
    		    if (i == 0) {
                    ERR_print_errors(bio_err);
                    die("could not write key file.\n");
    		    }
                fclose(fpub);
            }
        } else {
            // o2b
            rsa_key_ = (RSA *)calloc(1, sizeof(RSA));
            memset(rsa_key_, 0, sizeof(RSA));
            if (rsa_key_ == NULL) {
                die("could not allocate memory for RSA structure.\n");
            }
            if (kpriv) {
                fpriv = fopen (argv[4], "r");
                rsa_key_ = PEM_read_RSAPrivateKey(fpriv, NULL, NULL, NULL);
                fclose(fpriv);
                if (rsa_key_ == NULL) {
                    ERR_print_errors(bio_err);
                    die("could not load private key.\n");
                }
                openssl_to_private(rsa_key_, &private_key);
                fpriv = fopen(argv[5], "w");
                if (!fpriv) {
                    die("fopen");
                }
                print_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key));
            } else {
                fpub = fopen (argv[4], "r");
                rsa_key_ = PEM_read_RSA_PUBKEY(fpub, NULL, NULL, NULL);
                fclose(fpub);
                if (rsa_key_ == NULL) {
                    ERR_print_errors(bio_err);
                    die("could not load public key.\n");
                }
                openssl_to_keys(rsa_key_, 1024, private_key, public_key);
                //openssl_to_public(rsa_key_, &public_key);
                public_to_openssl(public_key, rsa_key_); //
                fpub = fopen(argv[5], "w");
                if (!fpub) {
                    die("fopen");
                }
                print_key_hex(fpub, (KEY*)&public_key, sizeof(public_key));
            }
        }
    } else {
        usage();
        exit(1);
    }
    return 0;
}
Пример #7
0
int
main(int argc, char *argv[])
{
	int rc;

	pesign_context ctx, *ctxp = &ctx;

	int list = 0;
	int remove = 0;

	char *digest_name = "sha256";

	poptContext optCon;
	struct poptOption options[] = {
		{NULL, '\0', POPT_ARG_INTL_DOMAIN, "pesign" },
		{"in", 'i', POPT_ARG_STRING, &ctx.infile, 0,
			"specify input file", "<infile>"},
		{"out", 'o', POPT_ARG_STRING, &ctx.outfile, 0,
			"specify output file", "<outfile>" },
		{"certficate", 'c', POPT_ARG_STRING, &ctx.cms_ctx.certname, 0,
			"specify certificate nickname",
			"<certificate nickname>" },
		{"privkey", 'p', POPT_ARG_STRING, &ctx.privkeyfile, 0,
			"specify private key file", "<privkey>" },
		{"force", 'f', POPT_ARG_VAL, &ctx.force,  1,
			"force overwriting of output file", NULL },
		{"nogaps", 'n',
			POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN,
			&ctx.hashgaps, 0,
			"skip gaps between sections when signing", NULL },
		{"sign", 's', POPT_ARG_VAL, &ctx.sign, 1,
			"create a new signature", NULL },
		{"hash", 'h', POPT_ARG_VAL, &ctx.hash, 1, "hash binary", NULL },
		{"digest_type", 'd', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
			&digest_name, 0, "digest type to use for pe hash" },
		{"import-signature", 'm',
			POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN,
			&ctx.insig, 0,"import signature from file", "<insig>" },
		{"signature-number", 'u', POPT_ARG_INT, &ctx.signum, -1,
			"specify which signature to operate on","<sig-number>"},
		{"list-signatures", 'l',
			POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN,
			&list, 1, "list signatures", NULL },
		{"show-signature", 'S', POPT_ARG_VAL, &list, 1,
			"show signature", NULL },
		{"remove-signature", 'r', POPT_ARG_VAL, &remove, 1,
			"remove signature" },
		{"export-signature", 'e',
			POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN,
			&ctx.outsig, 0,"export signature to file", "<outsig>" },
		{"export-pubkey", 'K', POPT_ARG_STRING,
			&ctx.outkey, 0, "export pubkey to file", "<outkey>" },
		{"export-cert", 'C', POPT_ARG_STRING,
			&ctx.outcert, 0, "export signing cert to file",
			"<outcert>" },
		{"ascii-armor", 'a', POPT_ARG_VAL, &ctx.ascii, 1,
			"use ascii armoring", NULL },
		POPT_AUTOALIAS
		POPT_AUTOHELP
		POPT_TABLEEND
	};

	rc = pesign_context_init(ctxp);
	if (rc < 0) {
		fprintf(stderr, "Could not initialize context: %m\n");
		exit(1);
	}

	optCon = poptGetContext("pesign", argc, (const char **)argv, options,0);

	while ((rc = poptGetNextOpt(optCon)) > 0)
		;

	if (rc < -1) {
		fprintf(stderr, "pesign: Invalid argument: %s: %s\n",
			poptBadOption(optCon, 0), poptStrerror(rc));
		exit(1);
	}

	if (poptPeekArg(optCon)) {
		fprintf(stderr, "pesign: Invalid Argument: \"%s\"\n",
				poptPeekArg(optCon));
		exit(1);
	}

	poptFreeContext(optCon);

	rc = set_digest_parameters(&ctx.cms_ctx, digest_name);
	int is_help  = strcmp(digest_name, "help") ? 0 : 1;
	if (rc < 0) {
		if (!is_help) {
			fprintf(stderr, "Digest \"%s\" not found.\n",
				digest_name);
		}
		exit(!is_help);
	}

	int action = 0;
	if (ctx.insig)
		action |= IMPORT_SIGNATURE;

	if (ctx.outkey)
		action |= EXPORT_PUBKEY;

	if (ctx.outcert)
		action |= EXPORT_CERT;

	if (ctx.outsig)
		action |= EXPORT_SIGNATURE;

	if (remove != 0)
		action |= REMOVE_SIGNATURE;

	if (list != 0)
		action |= LIST_SIGNATURES;

	if (ctx.sign) {
		action |= GENERATE_SIGNATURE;
		if (!(action & EXPORT_SIGNATURE))
			action |= IMPORT_SIGNATURE;
	}

	if (ctx.hash)
		action |= GENERATE_DIGEST|PRINT_DIGEST;

	SECItem newsig;

	switch (action) {
		case NO_FLAGS:
			fprintf(stderr, "pesign: Nothing to do.\n");
			exit(0);
			break;
		/* add a signature from a file */
		case IMPORT_SIGNATURE:
			check_inputs(ctxp);
			open_input(ctxp);
			open_output(ctxp);
			close_input(ctxp);
			open_sig_input(ctxp);
			import_signature(ctxp);
			close_sig_input(ctxp);
			close_output(ctxp);
			break;
		case EXPORT_PUBKEY:
			rc = find_certificate(&ctx.cms_ctx);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctx.cms_ctx.certname);
				exit(1);
			}
			open_pubkey_output(ctxp);
			export_pubkey(ctxp);
			break;
		case EXPORT_CERT:
			rc = find_certificate(&ctx.cms_ctx);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctx.cms_ctx.certname);
				exit(1);
			}
			open_cert_output(ctxp);
			export_cert(ctxp);
			break;
		/* find a signature in the binary and save it to a file */
		case EXPORT_SIGNATURE:
			open_input(ctxp);
			open_sig_output(ctxp);
			if (ctx.signum > ctx.cms_ctx.num_signatures) {
				fprintf(stderr, "Invalid signature number.\n");
				exit(1);
			}
			SECItem *sig = ctx.cms_ctx.signatures[ctx.signum];
			export_signature(ctxp, sig);
			close_input(ctxp);
			close_sig_output(ctxp);
			break;
		/* remove a signature from the binary */
		case REMOVE_SIGNATURE:
			check_inputs(ctxp);
			open_input(ctxp);
			open_output(ctxp);
			close_input(ctxp);
			if (ctx.signum > ctx.cms_ctx.num_signatures) {
				fprintf(stderr, "Invalid signature number.\n");
				exit(1);
			}
			remove_signature(&ctx);
			close_output(ctxp);
			break;
		/* list signatures in the binary */
		case LIST_SIGNATURES:
			open_input(ctxp);
			list_signatures(ctxp);
			break;
		case GENERATE_DIGEST|PRINT_DIGEST:
			open_input(ctxp);
			generate_digest(ctxp, ctx.inpe);
			print_digest(ctxp);
			break;
		/* generate a signature and save it in a separate file */
		case EXPORT_SIGNATURE|GENERATE_SIGNATURE:
			rc = find_certificate(&ctx.cms_ctx);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctx.cms_ctx.certname);
				exit(1);
			}
			open_input(ctxp);
			open_sig_output(ctxp);
			generate_digest(ctxp, ctx.inpe);
			generate_signature(ctxp, &newsig);
			export_signature(ctxp, &newsig);
			break;
		/* generate a signature and embed it in the binary */
		case IMPORT_SIGNATURE|GENERATE_SIGNATURE:
			check_inputs(ctxp);
			rc = find_certificate(&ctx.cms_ctx);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctx.cms_ctx.certname);
				exit(1);
			}
			open_input(ctxp);
			open_output(ctxp);
			close_input(ctxp);
			generate_digest(ctxp, ctx.outpe);
			generate_signature(ctxp, &newsig);
			insert_signature(ctxp, &newsig);
			close_output(ctxp);
			break;
		default:
			fprintf(stderr, "Incompatible flags (0x%08x): ", action);
			for (int i = 1; i < FLAG_LIST_END; i <<= 1) {
				if (action & i)
					print_flag_name(stderr, i);
			}
			fprintf(stderr, "\n");
			exit(1);
	}
	pesign_context_fini(&ctx);
	return (rc < 0);
}
Пример #8
0
int
main(int argc, char *argv[])
{
	int rc;

	pesign_context *ctxp;

	int list = 0;
	int remove = 0;
	int daemon = 0;
	int fork = 1;
	int padding = 0;
	int need_db = 0;

	char *digest_name = "sha256";
	char *tokenname = "NSS Certificate DB";
	char *origtoken = tokenname;
	char *certname = NULL;
	char *certdir = "/etc/pki/pesign";
	char *signum = NULL;

	rc = pesign_context_new(&ctxp);
	if (rc < 0) {
		fprintf(stderr, "Could not initialize context: %m\n");
		exit(1);
	}

	poptContext optCon;
	struct poptOption options[] = {
		{NULL, '\0', POPT_ARG_INTL_DOMAIN, "pesign" },
		{"in", 'i', POPT_ARG_STRING, &ctxp->infile, 0,
			"specify input file", "<infile>"},
		{"out", 'o', POPT_ARG_STRING, &ctxp->outfile, 0,
			"specify output file", "<outfile>" },
		{"certficate", 'c', POPT_ARG_STRING, &certname, 0,
			"specify certificate nickname",
			"<certificate nickname>" },
		{"certdir", 'n', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
			&certdir, 0,
			"specify nss certificate database directory",
			"<certificate directory path>" },
		{"force", 'f', POPT_ARG_VAL, &ctxp->force,  1,
			"force overwriting of output file", NULL },
		{"sign", 's', POPT_ARG_VAL, &ctxp->sign, 1,
			"create a new signature", NULL },
		{"hash", 'h', POPT_ARG_VAL, &ctxp->hash, 1,
			"hash binary", NULL },
		{"digest_type", 'd', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
			&digest_name, 0, "digest type to use for pe hash" },
		{"import-signed-certificate", 'm',
			POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN,
			&ctxp->insig, 0,"import signature from file", "<insig>" },
		{"export-signed-attributes", 'E',
			POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN,
			&ctxp->outsattrs, 0, "export signed attributes to file",
			"<signed_attributes_file>" },
		{"import-signed-attributes", 'I',
			POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN,
			&ctxp->insattrs, 0,
			"import signed attributes from file",
			"<signed_attributes_file>" },
		{"import-raw-signature", 'R',
			POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ctxp->rawsig,
			0, "import raw signature from file", "<inraw>" },
		{"signature-number", 'u', POPT_ARG_STRING, &signum, 0,
			"specify which signature to operate on","<sig-number>"},
		{"list-signatures", 'l',
			POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN,
			&list, 1, "list signatures", NULL },
		{"nss-token", 't', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
			&tokenname, 0, "NSS token holding signing key" },
		{"show-signature", 'S', POPT_ARG_VAL, &list, 1,
			"show signature", NULL },
		{"remove-signature", 'r', POPT_ARG_VAL, &remove, 1,
			"remove signature" },
		{"export-signature", 'e',
			POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN,
			&ctxp->outsig, 0,
			"export signature to file", "<outsig>" },
		{"export-pubkey", 'K', POPT_ARG_STRING,
			&ctxp->outkey, 0, "export pubkey to file", "<outkey>" },
		{"export-cert", 'C', POPT_ARG_STRING,
			&ctxp->outcert, 0, "export signing cert to file",
			"<outcert>" },
		{"ascii-armor", 'a', POPT_ARG_VAL, &ctxp->ascii, 1,
			"use ascii armoring", NULL },
		{"daemonize", 'D', POPT_ARG_VAL, &daemon, 1,
			"run as a daemon process", NULL },
		{"nofork", 'N', POPT_ARG_VAL, &fork, 0,
			"don't fork when daemonizing", NULL },
		{"verbose", 'v', POPT_ARG_VAL, &ctxp->verbose, 1,
			"be very verbose", NULL },
		{"padding", 'P', POPT_ARG_VAL,
			&padding, 1, "pad data section", NULL },
		POPT_AUTOALIAS
		POPT_AUTOHELP
		POPT_TABLEEND
	};

	optCon = poptGetContext("pesign", argc, (const char **)argv, options,0);

	rc = poptReadDefaultConfig(optCon, 0);
	if (rc < 0 && !(rc == POPT_ERROR_ERRNO && errno == ENOENT)) {
		fprintf(stderr, "pesign: poptReadDefaultConfig failed: %s\n",
		poptStrerror(rc));
		exit(1);
	}

	while ((rc = poptGetNextOpt(optCon)) > 0)
		;

	if (rc < -1) {
		fprintf(stderr, "pesign: Invalid argument: %s: %s\n",
			poptBadOption(optCon, 0), poptStrerror(rc));
		exit(1);
	}

	if (poptPeekArg(optCon)) {
		fprintf(stderr, "pesign: Invalid Argument: \"%s\"\n",
				poptPeekArg(optCon));
		exit(1);
	}

	poptFreeContext(optCon);

	if (signum) {
		errno = 0;
		ctxp->signum = strtol(signum, NULL, 0);
		if (errno != 0) {
			fprintf(stderr, "invalid signature number: %m\n");
			exit(1);
		}
	}

	int action = 0;
	if (daemon)
		action |= DAEMONIZE;

	if (ctxp->rawsig) {
		action |= IMPORT_RAW_SIGNATURE;
		need_db = 1;
	}

	if (ctxp->insattrs)
		action |= IMPORT_SATTRS;

	if (ctxp->outsattrs)
		action |= EXPORT_SATTRS;

	if (ctxp->insig)
		action |= IMPORT_SIGNATURE;

	if (ctxp->outkey) {
		action |= EXPORT_PUBKEY;
		need_db = 1;
	}

	if (ctxp->outcert) {
		action |= EXPORT_CERT;
		need_db = 1;
	}

	if (ctxp->outsig)
		action |= EXPORT_SIGNATURE;

	if (remove != 0)
		action |= REMOVE_SIGNATURE;

	if (list != 0)
		action |= LIST_SIGNATURES;

	if (ctxp->sign) {
		action |= GENERATE_SIGNATURE;
		if (!(action & EXPORT_SIGNATURE))
			action |= IMPORT_SIGNATURE;
		need_db = 1;
	}

	if (ctxp->hash)
		action |= GENERATE_DIGEST|PRINT_DIGEST;

	if (!daemon) {
		SECStatus status;
		if (need_db)
			status = NSS_Init(certdir);
		else
			status = NSS_NoDB_Init(NULL);
		if (status != SECSuccess) {
			fprintf(stderr, "Could not initialize nss: %s\n",
				PORT_ErrorToString(PORT_GetError()));
			exit(1);
		}

		status = register_oids(ctxp->cms_ctx);
		if (status != SECSuccess) {
			fprintf(stderr, "Could not register OIDs\n");
			exit(1);
		}
	}

	rc = set_digest_parameters(ctxp->cms_ctx, digest_name);
	int is_help  = strcmp(digest_name, "help") ? 0 : 1;
	if (rc < 0) {
		if (!is_help) {
			fprintf(stderr, "Digest \"%s\" not found.\n",
				digest_name);
		}
		exit(!is_help);
	}

	ctxp->cms_ctx->tokenname = tokenname ?
		PORT_ArenaStrdup(ctxp->cms_ctx->arena, tokenname) : NULL;
	if (tokenname && !ctxp->cms_ctx->tokenname) {
		fprintf(stderr, "could not allocate token name: %s\n",
			PORT_ErrorToString(PORT_GetError()));
		exit(1);
	}
	if (tokenname != origtoken)
		free(tokenname);

	ctxp->cms_ctx->certname = certname ?
		PORT_ArenaStrdup(ctxp->cms_ctx->arena, certname) : NULL;
	if (certname && !ctxp->cms_ctx->certname) {
		fprintf(stderr, "could not allocate certificate name: %s\n",
			PORT_ErrorToString(PORT_GetError()));
		exit(1);
	}
	if (certname)
		free(certname);


	if (ctxp->sign) {
		if (!ctxp->cms_ctx->certname) {
			fprintf(stderr, "pesign: signing requested but no "
				"certificate nickname provided\n");
			exit(1);
		}
	}

	ssize_t sigspace = 0;

	switch (action) {
		case NO_FLAGS:
			fprintf(stderr, "pesign: Nothing to do.\n");
			exit(0);
			break;
		/* in this case we have the actual binary signature and the
		 * signing cert, but not the pkcs7ish certificate that goes
		 * with it.
		 */
		case IMPORT_RAW_SIGNATURE|IMPORT_SATTRS:
			check_inputs(ctxp);
			rc = find_certificate(ctxp->cms_ctx, 0);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctxp->cms_ctx->certname);
				exit(1);
			}
			open_rawsig_input(ctxp);
			open_sattr_input(ctxp);
			import_raw_signature(ctxp);
			close_sattr_input(ctxp);
			close_rawsig_input(ctxp);

			open_input(ctxp);
			open_output(ctxp);
			close_input(ctxp);
			generate_digest(ctxp->cms_ctx, ctxp->outpe, 1);
			sigspace = calculate_signature_space(ctxp->cms_ctx,
								ctxp->outpe);
			allocate_signature_space(ctxp->outpe, sigspace);
			generate_signature(ctxp->cms_ctx);
			insert_signature(ctxp->cms_ctx, ctxp->signum);
			close_output(ctxp);
			break;
		case EXPORT_SATTRS:
			open_input(ctxp);
			open_sattr_output(ctxp);
			generate_digest(ctxp->cms_ctx, ctxp->inpe, 1);
			generate_sattr_blob(ctxp);
			close_sattr_output(ctxp);
			close_input(ctxp);
			break;
		/* add a signature from a file */
		case IMPORT_SIGNATURE:
			check_inputs(ctxp);
			if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) {
				fprintf(stderr, "Invalid signature number.\n");
				exit(1);
			}
			open_input(ctxp);
			open_output(ctxp);
			close_input(ctxp);
			open_sig_input(ctxp);
			parse_signature(ctxp);
			sigspace = get_sigspace_extend_amount(ctxp->cms_ctx,
					ctxp->outpe, &ctxp->cms_ctx->newsig);
			allocate_signature_space(ctxp->outpe, sigspace);
			check_signature_space(ctxp);
			insert_signature(ctxp->cms_ctx, ctxp->signum);
			close_sig_input(ctxp);
			close_output(ctxp);
			break;
		case EXPORT_PUBKEY:
			rc = find_certificate(ctxp->cms_ctx, 1);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctxp->cms_ctx->certname);
				exit(1);
			}
			open_pubkey_output(ctxp);
			export_pubkey(ctxp);
			break;
		case EXPORT_CERT:
			rc = find_certificate(ctxp->cms_ctx, 0);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctxp->cms_ctx->certname);
				exit(1);
			}
			open_cert_output(ctxp);
			export_cert(ctxp);
			break;
		/* find a signature in the binary and save it to a file */
		case EXPORT_SIGNATURE:
			open_input(ctxp);
			open_sig_output(ctxp);
			if (ctxp->signum > ctxp->cms_ctx->num_signatures) {
				fprintf(stderr, "Invalid signature number.\n");
				exit(1);
			}
			if (ctxp->signum < 0)
				ctxp->signum = 0;
			if (ctxp->signum >= ctxp->cms_ctx->num_signatures) {
				fprintf(stderr, "No valid signature #%d.\n",
					ctxp->signum);
				exit(1);
			}
			memcpy(&ctxp->cms_ctx->newsig,
				ctxp->cms_ctx->signatures[ctxp->signum],
				sizeof (ctxp->cms_ctx->newsig));
			export_signature(ctxp->cms_ctx, ctxp->outsigfd, ctxp->ascii);
			close_input(ctxp);
			close_sig_output(ctxp);
			memset(&ctxp->cms_ctx->newsig, '\0',
				sizeof (ctxp->cms_ctx->newsig));
			break;
		/* remove a signature from the binary */
		case REMOVE_SIGNATURE:
			check_inputs(ctxp);
			open_input(ctxp);
			open_output(ctxp);
			close_input(ctxp);
			if (ctxp->signum < 0 ||
					ctxp->signum >=
					ctxp->cms_ctx->num_signatures) {
				fprintf(stderr, "Invalid signature number %d.  "
					"Must be between 0 and %d.\n",
					ctxp->signum,
					ctxp->cms_ctx->num_signatures - 1);
				exit(1);
			}
			remove_signature(ctxp);
			close_output(ctxp);
			break;
		/* list signatures in the binary */
		case LIST_SIGNATURES:
			open_input(ctxp);
			list_signatures(ctxp);
			break;
		case GENERATE_DIGEST|PRINT_DIGEST:
			open_input(ctxp);
			generate_digest(ctxp->cms_ctx, ctxp->inpe, padding);
			print_digest(ctxp);
			break;
		/* generate a signature and save it in a separate file */
		case EXPORT_SIGNATURE|GENERATE_SIGNATURE:
			rc = find_certificate(ctxp->cms_ctx, 1);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctxp->cms_ctx->certname);
				exit(1);
			}
			open_input(ctxp);
			open_sig_output(ctxp);
			generate_digest(ctxp->cms_ctx, ctxp->inpe, 1);
			generate_signature(ctxp->cms_ctx);
			export_signature(ctxp->cms_ctx, ctxp->outsigfd, ctxp->ascii);
			break;
		/* generate a signature and embed it in the binary */
		case IMPORT_SIGNATURE|GENERATE_SIGNATURE:
			check_inputs(ctxp);
			rc = find_certificate(ctxp->cms_ctx, 1);
			if (rc < 0) {
				fprintf(stderr, "pesign: Could not find "
					"certificate %s\n",
					ctxp->cms_ctx->certname);
				exit(1);
			}
			if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) {
				fprintf(stderr, "Invalid signature number.\n");
				exit(1);
			}
			open_input(ctxp);
			open_output(ctxp);
			close_input(ctxp);
			generate_digest(ctxp->cms_ctx, ctxp->outpe, 1);
			sigspace = calculate_signature_space(ctxp->cms_ctx,
							     ctxp->outpe);
			allocate_signature_space(ctxp->outpe, sigspace);
			generate_digest(ctxp->cms_ctx, ctxp->outpe, 1);
			generate_signature(ctxp->cms_ctx);
			insert_signature(ctxp->cms_ctx, ctxp->signum);
			close_output(ctxp);
			break;
		case DAEMONIZE:
			rc = daemonize(ctxp->cms_ctx, certdir, fork);
			break;
		default:
			fprintf(stderr, "Incompatible flags (0x%08x): ", action);
			for (int i = 1; i < FLAG_LIST_END; i <<= 1) {
				if (action & i)
					print_flag_name(stderr, i);
			}
			fprintf(stderr, "\n");
			exit(1);
	}
	pesign_context_free(ctxp);

	if (!daemon) {
		SECStatus status = NSS_Shutdown();
		if (status != SECSuccess) {
			fprintf(stderr, "could not shut down NSS: %s",
				PORT_ErrorToString(PORT_GetError()));
			exit(1);
		}
	}

	return (rc < 0);
}