Exemple #1
0
/*
 * Return a connected stream
 */
static void *
bsd_stream_client(
    void *	h,
    int		id)
{
    struct sec_stream *bs = NULL;
    struct sec_handle *bh = h;
#ifdef DUMPER_SOCKET_BUFFERING
    int rcvbuf = sizeof(bs->databuf) * 2;
#endif

    assert(bh != NULL);

    bs = g_new0(struct sec_stream, 1);
    security_streaminit(&bs->secstr, &bsd_security_driver);
    bs->fd = stream_client(bh->hostname, (in_port_t)id,
	STREAM_BUFSIZE, STREAM_BUFSIZE, &bs->port, 0);
    if (bs->fd < 0) {
	security_seterror(&bh->sech,
	    _("can't connect stream to %s port %d: %s"), bh->hostname,
	    id, strerror(errno));
	amfree(bs->secstr.error);
	amfree(bs);
	return (NULL);
    }
    bs->socket = -1;	/* we're a client */
    bs->ev_read = NULL;
#ifdef DUMPER_SOCKET_BUFFERING
    setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, sizeof(rcvbuf));
#endif
    return (bs);
}
Exemple #2
0
/*
 * Forks a krb5 to the host listed in rc->hostname
 * Returns negative on error, with an errmsg in rc->errmsg.
 */
static int
runkrb5(
    struct sec_handle *	rh)
{
    struct servent *	sp;
    int			server_socket;
    in_port_t		my_port, port;
    struct tcp_conn *	rc = rh->rc;
    const char *err;

    if ((sp = getservbyname(AMANDA_KRB5_SERVICE_NAME, "tcp")) == NULL)
	port = htons(AMANDA_KRB5_DEFAULT_PORT);
    else
	port = sp->s_port;

    if ((err = get_tgt(keytab_name, principal_name)) != NULL) {
        security_seterror(&rh->sech, "%s: could not get TGT: %s",
            rc->hostname, err);
        return -1;
    }

    set_root_privs(1);
    server_socket = stream_client(rc->hostname,
				     (in_port_t)(ntohs(port)),
				     STREAM_BUFSIZE,
				     STREAM_BUFSIZE,
				     &my_port,
				     0);
    set_root_privs(0);

    if(server_socket < 0) {
	security_seterror(&rh->sech,
	    "%s", strerror(errno));
	
	return -1;
    }

    rc->read = rc->write = server_socket;

    if (gss_client(rh) < 0) {
	return -1;
    }


    return 0;
}
Exemple #3
0
int
connect_to_ndmp_proxy(char **errmsg)
{
    int   i;
    int   proxy_port;
    int   fd;

    *errmsg = NULL;
    proxy_port = getconf_int(CNF_NDMP_PROXY_PORT);

    if (proxy_port == 0) {
	*errmsg = g_strdup("no NDMP-PROXY-PORT configured; cannot start NDMP proxy");
    }

    /* we loop until getting a successful connection, either from a proxy we
     * launched or a proxy another process launched.  We only do this a few
     * times, though, in case there's some problem starting the proxy, or
     * something already running on that port. */
    for (i = 0; i < 3; i++) {
	g_debug("openning a connection to ndmp-proxy on port %d", proxy_port);
	fd = stream_client("localhost", proxy_port, 32768, 32768, NULL, 0);
	if (fd >= 0) {
	    g_debug("connected to ndmp-proxy");
	    return fd;
	}

	g_debug("Could not connect to ndmp-proxy: %s; trying to start a new instance",
		    strerror(errno));
	*errmsg = start_ndmp_proxy();
	if (*errmsg) {
	    return -1;
	}

    }

    *errmsg = stralloc(_("failed to open a connection to ndmp-proxy"));
    return -1;
}
Exemple #4
0
static void
stream_test(void)
{
	struct sockaddr_un sun;
	pid_t childpid;
	int listenfd;

	listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
	if (listenfd < 0)
		err(-1, "stream_test: socket");

	bzero(&sun, sizeof(sun));
	sun.sun_len = sizeof(sun);
	sun.sun_family = AF_UNIX;
	strcpy(sun.sun_path, socket_path);

	if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
		err(-1, "stream_test: bind");

	if (listen(listenfd, -1) < 0)
		err(-1, "stream_test: listen");

	childpid = fork();
	if (childpid < 0)
		err(-1, "stream_test: fork");

	if (childpid != 0) {
		sleep(1);
		stream_client();
		kill(childpid, SIGTERM);
		sleep(1);
	} else
		stream_server(listenfd);

	(void)unlink(socket_path);
}
Exemple #5
0
static int
do_directtcp_connect(
    XferElementGlue *self,
    DirectTCPAddr *addrs)
{
    XferElement *elt = XFER_ELEMENT(self);
    sockaddr_union addr;
    int sock;
#ifdef WORKING_IPV6
    char strsockaddr[INET6_ADDRSTRLEN + 20];
#else
    char strsockaddr[INET_ADDRSTRLEN + 20];
#endif

    if (!addrs) {
	g_debug("element-glue got no directtcp addresses to connect to!");
	if (!elt->cancelled) {
	    xfer_cancel_with_error(elt,
		"%s got no directtcp addresses to connect to",
		xfer_element_repr(elt));
	}
	goto cancel_wait;
    }

    /* set up the sockaddr -- IPv4 only */
    copy_sockaddr(&addr, addrs);

    str_sockaddr_r(&addr, strsockaddr, sizeof(strsockaddr));

    if (strncmp(strsockaddr,"255.255.255.255:", 16) == 0) {
	char  buffer[32770];
	char *s;
	int   size;
	char *data_host;
	int   data_port;

	g_debug("do_directtcp_connect making indirect data connection to %s",
		strsockaddr);
	data_port = SU_GET_PORT(&addr);
	sock = stream_client(NULL, "localhost", data_port,
                                   STREAM_BUFSIZE, 0, NULL, 0);
	if (sock < 0) {
	    xfer_cancel_with_error(elt, "stream_client(): %s", strerror(errno));
	    goto cancel_wait;
	}
	size = full_read(sock, buffer, 32768);
	if (size < 0 ) {
	    xfer_cancel_with_error(elt, "failed to read from indirecttcp: %s",
				   strerror(errno));
	    goto cancel_wait;
	}
	close(sock);
	buffer[size++] = ' ';
	buffer[size] = '\0';
	if ((s = strchr(buffer, ':')) == NULL) {
	    xfer_cancel_with_error(elt,
				   "Failed to parse indirect data stream: %s",
				   buffer);
	    goto cancel_wait;
	}
	*s++ = '\0';
	data_host = buffer;
	data_port = atoi(s);

	str_to_sockaddr(data_host, &addr);
	SU_SET_PORT(&addr, data_port);

	str_sockaddr_r(&addr, strsockaddr, sizeof(strsockaddr));
    }

    sock = socket(SU_GET_FAMILY(&addr), SOCK_STREAM, 0);

    g_debug("do_directtcp_connect making data connection to %s", strsockaddr);

    if (sock < 0) {
	xfer_cancel_with_error(elt,
	    "socket(): %s", strerror(errno));
	goto cancel_wait;
    }
    if (connect(sock, (struct sockaddr *)&addr, SS_LEN(&addr)) < 0) {
	xfer_cancel_with_error(elt,
	    "connect(): %s", strerror(errno));
	close(sock);
	goto cancel_wait;
    }

    g_debug("do_directtcp_connect: connected to %s, fd %d", strsockaddr, sock);

    return sock;

cancel_wait:
    wait_until_xfer_cancelled(elt->xfer);
    return -1;
}
Exemple #6
0
/*
 * Open a ssl connection to the host listed in rc->hostname
 * Returns negative on error, with an errmsg in rc->errmsg.
 */
static int
runssl(
    struct sec_handle *	rh,
    in_port_t port,
    char *src_ip,
    char *ssl_fingerprint_file,
    char *ssl_cert_file,
    char *ssl_key_file,
    char *ssl_ca_cert_file,
    char *ssl_cipher_list,
    int   ssl_check_certificate_host)
{
    int		     my_socket;
    in_port_t	     my_port;
    struct tcp_conn *rc = rh->rc;
    int              err;
    X509            *remote_cert;
    sockaddr_union   sin;
    socklen_t_equiv  len;

    if (!ssl_key_file) {
	security_seterror(&rh->sech, _("ssl-key-file must be set"));
	return -1;
    }

    if (!ssl_cert_file) {
	security_seterror(&rh->sech, _("ssl-cert-file must be set"));
	return -1;
    }

    my_socket = stream_client(src_ip,
				  rc->hostname,
				  port,
				  STREAM_BUFSIZE,
				  STREAM_BUFSIZE,
				  &my_port,
				  0);

    if(my_socket < 0) {
	security_seterror(&rh->sech,
	    "%s", strerror(errno));

	return -1;
    }

    rc->read = rc->write = my_socket;

    len = sizeof(sin);
    if (getpeername(my_socket, (struct sockaddr *)&sin, &len) < 0) {
	security_seterror(&rh->sech, _("getpeername returned: %s\n"), strerror(errno));
	return -1;
    }
    copy_sockaddr(&rc->peer, &sin);

    init_ssl();

    /* Create an SSL_CTX structure */
    rc->ctx = SSL_CTX_new(SSLv3_client_method());
    if (!rc->ctx) {
	security_seterror(&rh->sech, "%s",
			  ERR_error_string(ERR_get_error(), NULL));
	return -1;
    }
    SSL_CTX_set_mode(rc->ctx, SSL_MODE_AUTO_RETRY);

    if (ssl_cipher_list) {
	g_debug("Set ssl_cipher_list to %s", ssl_cipher_list);
	if (SSL_CTX_set_cipher_list(rc->ctx, ssl_cipher_list) == 0) {
	    security_seterror(&rh->sech, "%s",
		              ERR_error_string(ERR_get_error(), NULL));
	    return -1;
	}
    }

    /* Load the private-key corresponding to the remote certificate */
    g_debug("Loading ssl-key-file private-key %s", ssl_key_file);
    if (SSL_CTX_use_PrivateKey_file(rc->ctx, ssl_key_file,
				    SSL_FILETYPE_PEM) <= 0) {
	security_seterror(&rh->sech, "%s",
			  ERR_error_string(ERR_get_error(), NULL));
	return -1;
    }

    /* Load the me certificate into the SSL_CTX structure */
    g_debug("Loading ssl-cert-file certificate %s", ssl_cert_file);
    if (SSL_CTX_use_certificate_file(rc->ctx, ssl_cert_file,
				     SSL_FILETYPE_PEM) <= 0) {
	security_seterror(&rh->sech, "%s",
			  ERR_error_string(ERR_get_error(), NULL));
	return -1;
    }

    /* Check if the remote certificate and private-key matches */
    if (ssl_cert_file) {
	if (!SSL_CTX_check_private_key(rc->ctx)) {
	security_seterror(&rh->sech,
		_("Private key does not match the certificate public key"));
	return -1;
	}
    }

    if (ssl_ca_cert_file) {
        /* Load the RSA CA certificate into the SSL_CTX structure */
        /* This will allow this remote to verify the me's     */
        /* certificate.                                           */
	g_debug("Loading ssl-ca-cert-file ca %s", ssl_ca_cert_file);
        if (!SSL_CTX_load_verify_locations(rc->ctx, ssl_ca_cert_file, NULL)) {
	    security_seterror(&rh->sech, "%s",
			      ERR_error_string(ERR_get_error(), NULL));
	    return -1;
        }
    } else {
	g_debug(_("no ssl-ca-cert-file defined"));
    }

    /* Set flag in context to require peer (me) certificate */
    /* verification */
    if (ssl_ca_cert_file) {
	g_debug("Enabling certification verification");
	SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL);
	SSL_CTX_set_verify_depth(rc->ctx, 1);
    } else {
	g_debug("Not enabling certification verification");
    }

    /* ----------------------------------------------- */
    rc->ssl = SSL_new(rc->ctx);
    if (!rc->ssl) {
	security_seterror(&rh->sech, _("SSL_new failed: %s"),
			  ERR_error_string(ERR_get_error(), NULL));
	return -1;
    }
    SSL_set_connect_state(rc->ssl);

    /* Assign the socket into the SSL structure (SSL and socket without BIO) */
    SSL_set_fd(rc->ssl, my_socket);

    /* Perform SSL Handshake on the SSL remote */
    err = SSL_connect(rc->ssl);
    if (err == -1) {
	security_seterror(&rh->sech, _("SSL_connect failed: %s"),
			  ERR_error_string(ERR_get_error(), NULL));
	return -1;
    }

    /* Get the me's certificate (optional) */
    remote_cert = SSL_get_peer_certificate(rc->ssl);

    if (remote_cert == NULL) {
	security_seterror(&rh->sech, _("server have no certificate"));
	return -1;
    } else {
        char *str;

        str = X509_NAME_oneline(X509_get_subject_name(remote_cert), 0, 0);
        auth_debug(1, _("\t subject: %s\n"), str);
        amfree (str);

        str = X509_NAME_oneline(X509_get_issuer_name(remote_cert), 0, 0);
        auth_debug(1, _("\t issuer: %s\n"), str);
        amfree(str);

	if (ssl_check_certificate_host) {
	    int   loc = -1;
	    char *errmsg = NULL;
	    X509_NAME *x509_name = X509_get_subject_name(remote_cert);

	    loc = X509_NAME_get_index_by_NID(x509_name, NID_commonName, loc);
	    if (loc != -1) {
		X509_NAME_ENTRY *x509_entry = X509_NAME_get_entry(x509_name, loc);
		ASN1_STRING *asn1_string = X509_NAME_ENTRY_get_data(x509_entry);
		char *cert_hostname =  (char *)ASN1_STRING_data(asn1_string);
		auth_debug(1, "common_name: %s\n", cert_hostname);

		if (check_name_give_sockaddr((char*)cert_hostname,
				 (struct sockaddr *)&rc->peer, &errmsg) < 0) {
		    security_seterror(&rh->sech,
		       _("Common name of certicate (%s) doesn't resolv to IP (%s): %s"),
		       cert_hostname, str_sockaddr(&rc->peer), errmsg);
		    amfree(errmsg);
		    return -1;
		}
		auth_debug(1,
		         _("Certificate common name (%s) resolve to IP (%s)\n"),
			 cert_hostname, str_sockaddr(&rc->peer));
	    } else {
		security_seterror(&rh->sech,
				  _("Certificate have no common name"));
		g_debug("Certificate have no common name");
		return -1;
	    }
	}

/*
	if (ssl_dir) {
	    if (!ssl_fingerprint_file || ssl_fingerprint_file == '\0') {
		struct stat  statbuf;
		ssl_fingerprint_file = g_strdup_printf("%s/remote/%s/fingerprint", ssl_dir, cert_hostname);
		if (stat(ssl_fingerprint_file, &statbuf) == -1) {
		    g_free(ssl_fingerprint_file);
		    ssl_fingerprint_file = NULL;
		}
	    }
	}
*/

	if (ssl_fingerprint_file) {
            g_debug(_("run_ssl: Loading ssl-fingerprint-file %s"), ssl_fingerprint_file);
	    str = validate_fingerprints(remote_cert, ssl_fingerprint_file);
	    if (str) {
		security_seterror(&rh->sech, "%s", str);
		amfree(str);
		return -1;
	    }
	}
	X509_free (remote_cert);
    }

    g_debug(_("SSL_cipher: %s"), SSL_get_cipher(rc->ssl));

    return 0;
}