示例#1
0
文件: lka.c 项目: ryanakca/OpenSMTPD
static int
lka_X509_verify(struct ca_vrfy_req_msg *vrfy,
                const char *CAfile, const char *CRLfile)
{
    X509			*x509;
    X509			*x509_tmp;
    X509			*x509_tmp2;
    STACK_OF(X509)		*x509_chain;
    const unsigned char    	*d2i;
    size_t			i;
    int			ret = 0;
    const char		*errstr;

    x509 = NULL;
    x509_tmp = NULL;
    x509_chain = NULL;

    d2i = vrfy->cert;
    if (d2i_X509(&x509, &d2i, vrfy->cert_len) == NULL) {
        x509 = NULL;
        goto end;
    }

    if (vrfy->n_chain) {
        x509_chain = sk_X509_new_null();
        for (i = 0; i < vrfy->n_chain; ++i) {
            d2i = vrfy->chain_cert[i];
            if (d2i_X509(&x509_tmp, &d2i, vrfy->chain_cert_len[i]) == NULL) {
                x509_tmp = NULL;
                goto end;
            }

            if ((x509_tmp2 = X509_dup(x509_tmp)) == NULL)
                goto end;
            sk_X509_insert(x509_chain, x509_tmp2, i);
            x509_tmp = x509_tmp2 = NULL;
        }
    }
    if (! ca_X509_verify(x509, x509_chain, CAfile, NULL, &errstr))
        log_debug("debug: lka: X509 verify: %s", errstr);
    else
        ret = 1;

end:
    if (x509)
        X509_free(x509);
    if (x509_tmp)
        X509_free(x509_tmp);
    if (x509_chain)
        sk_X509_pop_free(x509_chain, X509_free);

    return ret;
}
示例#2
0
int
myproxy_ocsp_set_responder_cert(const char *path) {
    BIO *    in = NULL;
    X509 *   x  = NULL;
    int      count;
    int      rval = -1;

	sk_X509_pop_free(responder_cert, X509_free);
    responder_cert = NULL;

    in = BIO_new(BIO_s_file_internal());
    if (in == NULL || BIO_read_filename(in, path) <= 0) {
        verror_put_string("error reading %s", path);
        goto exit;
    }
    responder_cert = sk_X509_new_null();
    if (!responder_cert) {
        verror_put_string("sk_X509_new_null() failed in "
                          "myproxy_ocsp_set_responder_cert()");
        goto exit;
    }
    for (count = 0; ; count++) {
        x = PEM_read_bio_X509(in, NULL, NULL, NULL);
        if (x == NULL) {
            if ((ERR_GET_REASON(ERR_peek_error()) ==
                 PEM_R_NO_START_LINE) && (count > 0)) {
                ERR_clear_error();
                break;
            } else {
                verror_put_string("error reading %s", path);
                goto exit;
            }
        }
        sk_X509_insert(responder_cert,x,sk_X509_num(responder_cert));
        x = NULL;
    }

    rval = 0;                   /* success */

 exit:
    if (in) BIO_free_all(in);
    if (x)  X509_free(x);

    return rval;
}
static STACK_OF(X509) *
file_to_certs(const char *file)
{
	unsigned long ret;
	STACK_OF(X509) *certs;
	FILE *f;

	if ((f = fopen(file, "r")) == NULL) {
		warn("open failed %s", file);
		return NULL;
	}

	certs = sk_X509_new_null();
	for (;;) {
		X509 *cert;

		cert = PEM_read_X509(f, NULL, NULL, NULL);
		if (cert == NULL) {
			ret = ERR_GET_REASON(ERR_peek_error());
			if (ret == PEM_R_NO_START_LINE) {
				/* End of file reached. no error */
				ERR_clear_error();
				break;
			}
			sk_X509_free(certs);
			warnx("Can't read certificate in file: %s", file);
			fclose(f);
			return NULL;
		}
		sk_X509_insert(certs, cert, sk_X509_num(certs));
	}

	fclose(f);

	if (sk_X509_num(certs) == 0) {
		sk_X509_free(certs);
		certs = NULL;
		warnx("No certificate found in file %s", file);
	}

	return certs;
}
示例#4
0
文件: main.c 项目: jjolla/sslsplit
/*
 * Main entry point.
 */
int
main(int argc, char *argv[])
{
	const char *argv0;
	int ch;
	opts_t *opts;
	char *natengine;
	int pidfd = -1;
	int rv = EXIT_FAILURE;

	argv0 = argv[0];
	opts = opts_new();
	natengine = strdup(nat_getdefaultname());

	while ((ch = getopt(argc, argv, OPT_g OPT_G OPT_Z
	                    "k:c:C:K:t:OPs:e:Eu:j:p:l:L:S:dDVh")) != -1) {
		switch (ch) {
			case 'c':
				if (opts->cacrt)
					X509_free(opts->cacrt);
				opts->cacrt = ssl_x509_load(optarg);
				if (!opts->cacrt) {
					fprintf(stderr, "%s: error loading CA "
					                "cert from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				ssl_x509_refcount_inc(opts->cacrt);
				sk_X509_insert(opts->chain, opts->cacrt, 0);
				if (!opts->cakey) {
					opts->cakey = ssl_key_load(optarg);
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 'k':
				if (opts->cakey)
					EVP_PKEY_free(opts->cakey);
				opts->cakey = ssl_key_load(optarg);
				if (!opts->cakey) {
					fprintf(stderr, "%s: error loading CA "
					                "key from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				if (!opts->cacrt) {
					opts->cacrt = ssl_x509_load(optarg);
					if (opts->cacrt) {
						ssl_x509_refcount_inc(
						               opts->cacrt);
						sk_X509_insert(opts->chain,
						               opts->cacrt, 0);
					}
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 'C':
				if (ssl_x509chain_load(NULL, &opts->chain,
				                       optarg) == -1) {
					fprintf(stderr, "%s: error loading "
					                "chain from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				break;
			case 'K':
				if (opts->key)
					EVP_PKEY_free(opts->key);
				opts->key = ssl_key_load(optarg);
				if (!opts->key) {
					fprintf(stderr, "%s: error loading lea"
					                "f key from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
#ifndef OPENSSL_NO_DH
				if (!opts->dh) {
					opts->dh = ssl_dh_load(optarg);
				}
#endif /* !OPENSSL_NO_DH */
				break;
			case 't':
				if (!sys_isdir(optarg)) {
					fprintf(stderr, "%s: '%s' is not a "
					                "directory\n",
					                argv0, optarg);
					exit(EXIT_FAILURE);
				}
				if (opts->tgcrtdir)
					free(opts->tgcrtdir);
				opts->tgcrtdir = strdup(optarg);
				break;
			case 'O':
				opts->deny_ocsp = 1;
				break;
			case 'P':
				opts->passthrough = 1;
				break;
#ifndef OPENSSL_NO_DH
			case 'g':
				if (opts->dh)
					DH_free(opts->dh);
				opts->dh = ssl_dh_load(optarg);
				if (!opts->dh) {
					fprintf(stderr, "%s: error loading DH "
					                "params from '%s':\n",
					                argv0, optarg);
					if (errno) {
						fprintf(stderr, "%s\n",
						        strerror(errno));
					} else {
						ERR_print_errors_fp(stderr);
					}
					exit(EXIT_FAILURE);
				}
				break;
#endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_ECDH
			case 'G':
			{
				EC_KEY *ec;
				if (opts->ecdhcurve)
					free(opts->ecdhcurve);
				if (!(ec = ssl_ec_by_name(optarg))) {
					fprintf(stderr, "%s: unknown curve "
					                "'%s'\n",
					                argv0, optarg);
					exit(EXIT_FAILURE);
				}
				EC_KEY_free(ec);
				opts->ecdhcurve = strdup(optarg);
				break;
			}
#endif /* !OPENSSL_NO_ECDH */
#ifdef SSL_OP_NO_COMPRESSION
			case 'Z':
				opts->sslcomp = 0;
				break;
#endif /* SSL_OP_NO_COMPRESSION */
			case 's':
				if (opts->ciphers)
					free(opts->ciphers);
				opts->ciphers = strdup(optarg);
				break;
			case 'e':
				free(natengine);
				natengine = strdup(optarg);
				break;
			case 'E':
				nat_list_engines();
				exit(EXIT_SUCCESS);
				break;
			case 'u':
				if (opts->dropuser)
					free(opts->dropuser);
				opts->dropuser = strdup(optarg);
				break;
			case 'p':
				if (opts->pidfile)
					free(opts->pidfile);
				opts->pidfile = strdup(optarg);
				break;
			case 'j':
				if (opts->jaildir)
					free(opts->jaildir);
				opts->jaildir = strdup(optarg);
				break;
			case 'l':
				if (opts->connectlog)
					free(opts->connectlog);
				opts->connectlog = strdup(optarg);
				break;
			case 'L':
				if (opts->contentlog)
					free(opts->contentlog);
				opts->contentlog = strdup(optarg);
				opts->contentlogdir = 0;
				break;
			case 'S':
				if (opts->contentlog)
					free(opts->contentlog);
				opts->contentlog = strdup(optarg);
				opts->contentlogdir = 1;
				break;
			case 'd':
				opts->detach = 1;
				break;
			case 'D':
				log_dbg_mode(LOG_DBG_MODE_ERRLOG);
				opts->debug = 1;
				break;
			case 'V':
				main_version();
				exit(EXIT_SUCCESS);
			case 'h':
				main_usage();
				exit(EXIT_SUCCESS);
			case '?':
				exit(EXIT_FAILURE);
			default:
				main_usage();
				exit(EXIT_FAILURE);
		}
	}
	argc -= optind;
	argv += optind;
	opts->spec = proxyspec_parse(&argc, &argv, natengine);

	/* usage checks */
	if (opts->detach && OPTS_DEBUG(opts)) {
		fprintf(stderr, "%s: -d and -D are mutually exclusive.\n",
		                argv0);
		exit(EXIT_FAILURE);
	}
	if (!opts->spec) {
		fprintf(stderr, "%s: no proxyspec specified.\n", argv0);
		exit(EXIT_FAILURE);
	}
	for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
		if (spec->connect_addrlen || spec->sni_port)
			continue;
		if (!spec->natengine) {
			fprintf(stderr, "%s: no supported NAT engines "
			                "on this platform.\n"
			                "Only static addr and SNI proxyspecs "
			                "supported.\n", argv0);
			exit(EXIT_FAILURE);
		}
		if (spec->listen_addr.ss_family == AF_INET6 &&
		    !nat_ipv6ready(spec->natengine)) {
			fprintf(stderr, "%s: IPv6 not supported by '%s'\n",
			                argv0, spec->natengine);
			exit(EXIT_FAILURE);
		}
		spec->natlookup = nat_getlookupcb(spec->natengine);
		spec->natsocket = nat_getsocketcb(spec->natengine);
	}
	if (opts_has_ssl_spec(opts)) {
		if ((opts->cacrt || !opts->tgcrtdir) && !opts->cakey) {
			fprintf(stderr, "%s: no CA key specified (-k).\n",
			                argv0);
			exit(EXIT_FAILURE);
		}
		if (opts->cakey && !opts->cacrt) {
			fprintf(stderr, "%s: no CA cert specified (-c).\n",
			                argv0);
			exit(EXIT_FAILURE);
		}
		if (opts->cakey && opts->cacrt &&
		    (X509_check_private_key(opts->cacrt, opts->cakey) != 1)) {
			fprintf(stderr, "%s: CA cert does not match key.\n",
			                argv0);
			ERR_print_errors_fp(stderr);
			exit(EXIT_FAILURE);
		}
	}

	/* prevent multiple instances running */
	if (opts->pidfile) {
		pidfd = sys_pidf_open(opts->pidfile);
		if (pidfd == -1) {
			fprintf(stderr, "%s: cannot open PID file '%s' "
			                "- process already running?\n",
			                argv0, opts->pidfile);
			exit(EXIT_FAILURE);
		}
	}

	/* dynamic defaults */
	if (!opts->ciphers) {
		opts->ciphers = strdup("ALL:-aNULL");
		if (!opts->ciphers) {
			fprintf(stderr, "%s: out of memory.\n", argv0);
			exit(EXIT_FAILURE);
		}
	}
	if (!opts->jaildir && (geteuid() == 0) && !opts->contentlogdir) {
		opts->jaildir = strdup("/var/empty");
	}
	if (!opts->dropuser && !geteuid() && !getuid() &&
	    !opts->contentlogdir) {
		opts->dropuser = strdup("nobody");
	}
	if (opts_has_ssl_spec(opts) && !opts->key) {
		opts->key = ssl_key_genrsa(1024);
		if (!opts->key) {
			fprintf(stderr, "%s: error generating RSA key:\n",
			                argv0);
			ERR_print_errors_fp(stderr);
			exit(EXIT_FAILURE);
		}
		if (OPTS_DEBUG(opts)) {
			log_dbg_printf("Generated RSA key for leaf certs.\n");
		}
	}

	/* debugging */
	if (OPTS_DEBUG(opts)) {
		main_version();
		log_dbg_printf("proxyspecs:\n");
		for (proxyspec_t *spec = opts->spec; spec; spec = spec->next) {
			char *lbuf, *cbuf = NULL;
			lbuf = sys_sockaddr_str((struct sockaddr *)
			                        &spec->listen_addr,
			                        spec->listen_addrlen);
			if (spec->connect_addrlen) {
				cbuf = sys_sockaddr_str((struct sockaddr *)
				                        &spec->connect_addr,
				                        spec->connect_addrlen);
			}
			if (spec->sni_port) {
				asprintf(&cbuf, "sni %i", spec->sni_port);
			}
			log_dbg_printf("- %s %s %s %s\n", lbuf,
			               (spec->ssl ? "ssl" : "tcp"),
			               (spec->http ? "http" : "plain"),
			               (spec->natengine ? spec->natengine
			                                : cbuf));
			if (lbuf)
				free(lbuf);
			if (cbuf)
				free(cbuf);
		}
		if (opts->cacrt) {
			char *subj = ssl_x509_subject(opts->cacrt);
			log_dbg_printf("Loaded CA: '%s'\n", subj);
			free(subj);
#ifdef DEBUG_CERTIFICATE
			log_dbg_print_free(ssl_x509_to_str(opts->cacrt));
			log_dbg_print_free(ssl_x509_to_pem(opts->cacrt));
#endif /* DEBUG_CERTIFICATE */
		} else {
			log_dbg_printf("No CA loaded.\n");
		}
	}

	/*
	 * Initialize as much as possible before daemon() in order to be
	 * able to provide direct feedback to the user when failing.
	 */
	if (cachemgr_preinit() == -1) {
		fprintf(stderr, "%s: failed to preinit cachemgr.\n", argv0);
		exit(EXIT_FAILURE);
	}
	if (log_preinit(opts) == -1) {
		fprintf(stderr, "%s: failed to preinit logging.\n", argv0);
		exit(EXIT_FAILURE);
	}
	if (nat_preinit() == -1) {
		fprintf(stderr, "%s: failed to preinit NAT lookup.\n", argv0);
		exit(EXIT_FAILURE);
	}

	/* Bind listeners before dropping privileges */
	proxy_ctx_t *proxy = proxy_new(opts);
	if (!proxy) {
		fprintf(stderr, "%s: failed to initialize proxy.\n", argv0);
		exit(EXIT_FAILURE);
	}

	/* Drop privs, chroot, detach from TTY */
	if (sys_privdrop(opts->dropuser, opts->jaildir) == -1) {
		fprintf(stderr, "%s: failed to drop privileges: %s\n",
		                argv0, strerror(errno));
		exit(EXIT_FAILURE);
	}
	if (opts->detach) {
		if (OPTS_DEBUG(opts)) {
			log_dbg_printf("Detaching from TTY, see syslog for "
			               "errors after this point\n");
		}
		if (daemon(1, 0) == -1) {
			fprintf(stderr, "%s: failed to detach from TTY: %s\n",
			                argv0, strerror(errno));
			exit(EXIT_FAILURE);
		}
		log_err_mode(LOG_ERR_MODE_SYSLOG);
		ssl_reinit();
	}

	/* Post-privdrop/chroot/detach initialization, thread spawning */
	if (log_init(opts) == -1) {
		fprintf(stderr, "%s: failed to init log facility.\n", argv0);
		goto out_log_failed;
	}
	if (opts->pidfile && (sys_pidf_write(pidfd) == -1)) {
		log_err_printf("Failed to write PID to PID file '%s': %s\n",
		               opts->pidfile, strerror(errno));
		goto out_pidwrite_failed;
	}
	if (cachemgr_init() == -1) {
		log_err_printf("Failed to init cache manager.\n");
		goto out_cachemgr_failed;
	}
	if (nat_init() == -1) {
		log_err_printf("Failed to init NAT state table lookup.\n");
		goto out_nat_failed;
	}

	if (opts->tgcrtdir) {
		sys_dir_eachfile(opts->tgcrtdir, main_loadtgcrt, opts);
	}

	rv = EXIT_SUCCESS;

	proxy_run(proxy);
	proxy_free(proxy);
	nat_fini();
out_nat_failed:
	cachemgr_fini();
out_cachemgr_failed:
	if (opts->pidfile) {
		sys_pidf_close(pidfd, opts->pidfile);
	}
out_pidwrite_failed:
	log_fini();
out_log_failed:
	opts_free(opts);
	ssl_fini();
	return rv;
}
/**
 * This function copies a globus_gsi_callback_data_t.
 * @ingroup globus_gsi_callback_data
 *
 * @param source
 *        The structure to be copied
 * @param dest
 *        The destination of the copy
 *
 * @return
 *        GLOBUS_SUCCESS unless an error occurred, in which case, 
 *        a globus error object ID is returned
 */
globus_result_t
globus_gsi_callback_data_copy(
    globus_gsi_callback_data_t     source,
    globus_gsi_callback_data_t *   dest)
{
    int                                 index;
    globus_result_t                     result = GLOBUS_SUCCESS;
    static char *                       _function_name_ =
        "globus_gsi_callback_data_copy";

    GLOBUS_I_GSI_CALLBACK_DEBUG_ENTER;

    if(!source)
    {
        GLOBUS_GSI_CALLBACK_ERROR_RESULT(
            result,
            GLOBUS_GSI_CALLBACK_ERROR_CALLBACK_DATA,
            (_CLS("NULL callback data source parameter passed to function: %s"),
             _function_name_));
        goto exit;
    }

    if(!dest)
    {
        GLOBUS_GSI_CALLBACK_ERROR_RESULT(
            result,
            GLOBUS_GSI_CALLBACK_ERROR_CALLBACK_DATA,
            (_CLS("NULL callback data dest parameter passed to function: %s"),
             _function_name_));
        goto exit;
    }        

    globus_gsi_callback_data_init(dest);

    (*dest)->cert_depth = source->cert_depth;
    (*dest)->proxy_depth = source->proxy_depth;
    (*dest)->cert_type = source->cert_type;
    (*dest)->cert_chain = sk_X509_new_null();

    for(index = 0; index < sk_X509_num(source->cert_chain); ++index)
    {
        if(!sk_X509_insert((*dest)->cert_chain,
                           X509_dup(sk_X509_value(source->cert_chain, index)),
                           index))
        {
            GLOBUS_GSI_CALLBACK_OPENSSL_ERROR_RESULT(
                result,
                GLOBUS_GSI_CALLBACK_ERROR_CERT_CHAIN,
                (_CLS("Couldn't copy cert chain from callback data")));
            goto exit;
        }
    }

    (*dest)->cert_dir = strdup(source->cert_dir);
    (*dest)->extension_cb = source->extension_cb;

    /* just copy the pointer location - these get created
     * and destroyed in gss code
     */
    (*dest)->extension_oids = source->extension_oids;

    (*dest)->error = source->error;

 exit:
    GLOBUS_I_GSI_CALLBACK_DEBUG_EXIT;
    return result;
}
示例#6
0
int load_config() {
	string tmp;
	vector<string> splited;
	int tmpSize, tmpPort;

	if(configFilePath[0] == '\0') {
		strcpy(configFilePath, DEFAULT_CONFIG_FILE_PATH);
	}

	if(!options.read_options_file(configFilePath)) {
		log_message(ERROR_LOG, "Couldn't read configuration file %s.", configFilePath);
		return 1;
	}

	tmp = options["logLevel"];
	config.logLevel = atoi(tmp.c_str());

	tmp = options["maxClients"];
	config.maxClients = atoi(tmp.c_str());

	config.logFilePath = options["logFilePath"];

	tmp = options["bindPort"];
	config.bindPort = atoi(tmp.c_str());

	tmp = options["sslPorts"];
	splited = split(tmp, ',');
	tmpSize = splited.size();
	for(int i=0; i<tmpSize; i++) {
		tmpPort = atoi(splited.at(i).c_str());
		if((tmpPort >= 0) && (tmpPort <= 65535)) {
			config.sslPorts.push_back(tmpPort);
		}
	}

	/* load certificate */
	tmp = options["cacrt"];
	config.cacrt = ssl_x509_load(tmp.c_str());
	if(!config.cacrt) {
		log_message(ERROR_LOG, "Could not loading ca crt %s.", tmp.c_str());
		return 1;
	}

	config.chain = sk_X509_new_null();
	ssl_x509_refcount_inc(config.cacrt);
	sk_X509_insert(config.chain, config.cacrt, 0);

	tmp = options["cakey"];
	config.cakey = ssl_key_load(tmp.c_str());
	if (!config.cakey) {
		log_message(ERROR_LOG, "Could not loading ca key %s.", tmp.c_str());
		return 1;
	}

	tmp = options["leafkey"];
	config.key = ssl_key_load(tmp.c_str());
	if (!config.key) {
		log_message(ERROR_LOG, "Could not loading leaf key %s.", tmp.c_str());
		return 1;
	}

	config.ciphers = strdup("ALL:-aNULL");
	if (!config.ciphers) {
		log_message(ERROR_LOG, "Could not malloc ciphers.");
		return 1;
	}

	tmp = options["contentLogDir"];
	config.contentLogDir = strdup(tmp.c_str());
	if (!config.contentLogDir) {
		log_message(ERROR_LOG, "Could not malloc contentLogDir.");
		return 1;
	}

	if (!sys_isdir(config.contentLogDir)) {
		log_message(ERROR_LOG, "%s is not a directory.", config.contentLogDir);
		return 1;
	}

	return 0;
}