Esempio n. 1
0
static Channel *
server_request_direct_tcpip(struct ssh *ssh)
{
	Channel *c = NULL;
	char *target, *originator;
	u_int target_port, originator_port;
	int r;

	if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
	    (r = sshpkt_get_u32(ssh, &target_port)) != 0 ||
	    (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
	    (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
	    (r = sshpkt_get_end(ssh)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));

	debug("server_request_direct_tcpip: originator %s port %d, target %s "
	    "port %d", originator, originator_port, target, target_port);

	/* XXX fine grained permissions */
	if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
	    !no_port_forwarding_flag) {
		c = channel_connect_to_port(ssh, target, target_port,
		    "direct-tcpip", "direct-tcpip");
	} else {
		logit("refused local port forward: "
		    "originator %s port %d, target %s port %d",
		    originator, originator_port, target, target_port);
	}

	free(originator);
	free(target);

	return c;
}
Esempio n. 2
0
static int
server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
{
	Channel *c = NULL;
	char *ctype = 0;
	int r;
	u_int rchan, rmaxpack, rwindow;
	size_t len;

	if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 ||
	    (r = sshpkt_get_u32(ssh, &rchan)) != 0 ||
	    (r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
	    (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
		goto out;

	debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
	    ctype, rchan, rwindow, rmaxpack);

	if (strcmp(ctype, "session") == 0) {
		c = server_request_session(ssh);
	} else if (strcmp(ctype, "direct-tcpip") == 0) {
		c = server_request_direct_tcpip(ssh);
	} else if (strcmp(ctype, "*****@*****.**") == 0) {
		c = server_request_direct_streamlocal(ssh);
	} else if (strcmp(ctype, "*****@*****.**") == 0) {
		c = server_request_tun(ssh);
	}
	if (c != NULL) {
		debug("server_input_channel_open: confirm %s", ctype);
		c->remote_id = rchan;
		c->remote_window = rwindow;
		c->remote_maxpacket = rmaxpack;
		if (c->type != SSH_CHANNEL_CONNECTING) {
			if ((r = sshpkt_start(ssh,
			    SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
			    (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
			    (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
			    (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
			    (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0||
			    (r = sshpkt_send(ssh)) != 0)
				goto out;
		}
	} else {
		debug("server_input_channel_open: failure %s", ctype);
		if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
		    (r = sshpkt_put_u32(ssh, rchan)) != 0 ||
		    (r = sshpkt_put_u32(ssh,
		    SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) != 0 ||
		    (!(ssh->compat & SSH_BUG_OPENFAILURE) &&
		    (r = sshpkt_put_cstring(ssh, "open failed")) != 0) ||
		    (!(ssh->compat & SSH_BUG_OPENFAILURE) &&
		    (r = sshpkt_put_cstring(ssh, "")) != 0) ||
		    (r = sshpkt_send(ssh)) != 0)
			goto out;
	}
	r = 0;
 out:
	free(ctype);
	return r;
}
Esempio n. 3
0
char *
ssh_packet_get_cstring(struct ssh *ssh, u_int *length_ptr)
{
	int r;
	size_t len;
	char *val;

	if ((r = sshpkt_get_cstring(ssh, &val, &len)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));
	if (length_ptr != NULL)
		*length_ptr = (u_int)len;
	return val;
}
Esempio n. 4
0
static int
userauth_passwd(struct ssh *ssh)
{
	char *password;
	int authenticated = 0, r;
	u_char change;
	size_t len;

	if ((r = sshpkt_get_u8(ssh, &change)) != 0 ||
	    (r = sshpkt_get_cstring(ssh, &password, &len)) != 0 ||
	    (change && (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) ||
	    (r = sshpkt_get_end(ssh)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));

	if (change)
		logit("password change not supported");
	else if (PRIVSEP(auth_password(ssh, password)) == 1)
		authenticated = 1;
	explicit_bzero(password, len);
	free(password);
	return authenticated;
}
Esempio n. 5
0
int
kex_input_ext_info(int type, u_int32_t seq, void *ctxt)
{
	struct ssh *ssh = ctxt;
	struct kex *kex = ssh->kex;
	u_int32_t i, ninfo;
	char *name, *val, *found;
	int r;

	debug("SSH2_MSG_EXT_INFO received");
	ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
	if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
		return r;
	for (i = 0; i < ninfo; i++) {
		if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
			return r;
		if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) {
			free(name);
			return r;
		}
		debug("%s: %s=<%s>", __func__, name, val);
		if (strcmp(name, "server-sig-algs") == 0) {
			found = match_list("rsa-sha2-256", val, NULL);
			if (found) {
				kex->rsa_sha2 = 256;
				free(found);
			}
			found = match_list("rsa-sha2-512", val, NULL);
			if (found) {
				kex->rsa_sha2 = 512;
				free(found);
			}
		}
		free(name);
		free(val);
	}
	return sshpkt_get_end(ssh);
}
Esempio n. 6
0
static int
server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
{
	Channel *c;
	int r, success = 0;
	u_int id;
	u_char reply;
	char *rtype = NULL;

	if ((r = sshpkt_get_u32(ssh, &id)) != 0 ||
	    (r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
	    (r = sshpkt_get_u8(ssh, &reply)) != 0)
		goto out;

	debug("server_input_channel_req: channel %u request %s reply %d",
	    id, rtype, reply);

	if ((c = channel_lookup(id)) == NULL)
		ssh_packet_disconnect(ssh, "server_input_channel_req: "
		    "unknown channel %u", id);
	if (!strcmp(rtype, "*****@*****.**")) {
		if ((r = sshpkt_get_end(ssh)) != 0)
			goto out;
		chan_rcvd_eow(c);
	} else if ((c->type == SSH_CHANNEL_LARVAL ||
	    c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
		success = session_input_channel_req(c, rtype);
	if (reply && !(c->flags & CHAN_CLOSE_SENT)) {
		if ((r = sshpkt_start(ssh, success ? SSH2_MSG_CHANNEL_SUCCESS :
		    SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
		    (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
		    (r = sshpkt_send(ssh)) != 0)
			goto out;
	}
	r = 0;
 out:
	if (rtype)
		free(rtype);
	return r;
}
Esempio n. 7
0
/*ARGSUSED*/
static int
input_service_request(int type, u_int32_t seq, struct ssh *ssh)
{
    struct authctxt *authctxt = ssh->authctxt;
    char *service = NULL;
    int r, acceptit = 0;

    if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 ||
            (r = sshpkt_get_end(ssh)) != 0)
        goto out;

    if (authctxt == NULL)
        fatal("input_service_request: no authctxt");

    if (strcmp(service, "ssh-userauth") == 0) {
        if (!authctxt->success) {
            acceptit = 1;
            /* now we can handle user-auth requests */
            ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST,
                             &input_userauth_request);
        }
    }
    /* XXX all other service requests are denied */

    if (acceptit) {
        if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_ACCEPT)) != 0 ||
                (r = sshpkt_put_cstring(ssh, service)) != 0 ||
                (r = sshpkt_send(ssh)) != 0)
            goto out;
        ssh_packet_write_wait(ssh);
    } else {
        debug("bad service request %s", service);
        ssh_packet_disconnect(ssh, "bad service request %s", service);
    }
    r = 0;
out:
    free(service);
    return r;
}
Esempio n. 8
0
/*ARGSUSED*/
static int
input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
{
    struct authctxt *authctxt = ssh->authctxt;
    struct authmethod *m = NULL;
    char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
    int r, authenticated = 0;

    if (authctxt == NULL)
        fatal("input_userauth_request: no authctxt");

    if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 ||
            (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 ||
            (r = sshpkt_get_cstring(ssh, &method, NULL)) != 0)
        goto out;
    debug("userauth-request for user %s service %s method %s", user, service, method);
    debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

    if ((style = strchr(user, ':')) != NULL)
        *style++ = 0;

    if (authctxt->attempt++ == 0) {
        /* setup auth context */
        authctxt->pw = PRIVSEP(getpwnamallow(user));
        if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
            authctxt->valid = 1;
            debug2("input_userauth_request: setting up authctxt for %s", user);
        } else {
            logit("input_userauth_request: invalid user %s", user);
            authctxt->pw = fakepw();
        }
        setproctitle("%s%s", authctxt->valid ? user : "******",
                     use_privsep ? " [net]" : "");
        authctxt->user = xstrdup(user);
        authctxt->service = xstrdup(service);
        authctxt->style = style ? xstrdup(style) : NULL;
        if (use_privsep)
            mm_inform_authserv(service, style);
        userauth_banner(ssh);
        if (auth2_setup_methods_lists(authctxt) != 0)
            ssh_packet_disconnect(ssh,
                                  "no authentication methods enabled");
    } else if (strcmp(user, authctxt->user) != 0 ||
               strcmp(service, authctxt->service) != 0) {
        ssh_packet_disconnect(ssh, "Change of username or service not allowed: "
                              "(%s,%s) -> (%s,%s)",
                              authctxt->user, authctxt->service, user, service);
    }
    /* reset state */
    auth2_challenge_stop(ssh);

#ifdef GSSAPI
    /* XXX move to auth2_gssapi_stop() */
    ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
    ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif

    authctxt->postponed = 0;
    authctxt->server_caused_failure = 0;

    /* try to authenticate user */
    m = authmethod_lookup(authctxt, method);
    if (m != NULL && authctxt->failures < options.max_authtries) {
        debug2("input_userauth_request: try method %s", method);
        authenticated =	m->userauth(ssh);
    }
    userauth_finish(ssh, authenticated, method, NULL);
    r = 0;
out:
    free(service);
    free(user);
    free(method);
    return r;
}
Esempio n. 9
0
static int
userauth_hostbased(struct ssh *ssh)
{
	Authctxt *authctxt = ssh->authctxt;
	struct sshbuf *b;
	struct sshkey *key = NULL;
	char *pkalg, *cuser, *chost;
	u_char *pkblob, *sig;
	size_t alen, blen, slen;
	int r, pktype, authenticated = 0;

	if (!authctxt->valid) {
		debug2("%s: disabled because of invalid user", __func__);
		return 0;
	}
	/* XXX use sshkey_froms() */
	if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 ||
	    (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
	    (r = sshpkt_get_cstring(ssh, &chost, NULL)) != 0 ||
	    (r = sshpkt_get_cstring(ssh, &cuser, NULL)) != 0 ||
	    (r = sshpkt_get_string(ssh, &sig, &slen)) != 0)
		fatal("%s: packet parsing: %s", __func__, ssh_err(r));

	debug("%s: cuser %s chost %s pkalg %s slen %zu", __func__,
	    cuser, chost, pkalg, slen);
#ifdef DEBUG_PK
	debug("signature:");
	sshbuf_dump_data(sig, siglen, stderr);
#endif
	pktype = sshkey_type_from_name(pkalg);
	if (pktype == KEY_UNSPEC) {
		/* this is perfectly legal */
		logit("%s: unsupported public key algorithm: %s",
		    __func__, pkalg);
		goto done;
	}
	if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
		error("%s: key_from_blob: %s", __func__, ssh_err(r));
		goto done;
	}
	if (key == NULL) {
		error("%s: cannot decode key: %s", __func__, pkalg);
		goto done;
	}
	if (key->type != pktype) {
		error("%s: type mismatch for decoded key "
		    "(received %d, expected %d)", __func__, key->type, pktype);
		goto done;
	}
	if (sshkey_type_plain(key->type) == KEY_RSA &&
	    (ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
		error("Refusing RSA key because peer uses unsafe "
		    "signature format");
		goto done;
	}
	if (match_pattern_list(sshkey_ssh_name(key),
	    options.hostbased_key_types, 0) != 1) {
		logit("%s: key type %s not in HostbasedAcceptedKeyTypes",
		    __func__, sshkey_type(key));
		goto done;
	}

	if ((b = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);
	/* reconstruct packet */
	if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
	    (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
	    (r = sshbuf_put_cstring(b, authctxt->user)) != 0 ||
	    (r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
	    (r = sshbuf_put_cstring(b, "hostbased")) != 0 ||
	    (r = sshbuf_put_string(b, pkalg, alen)) != 0 ||
	    (r = sshbuf_put_string(b, pkblob, blen)) != 0 ||
	    (r = sshbuf_put_cstring(b, chost)) != 0 ||
	    (r = sshbuf_put_cstring(b, cuser)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
#ifdef DEBUG_PK
	sshbuf_dump(b, stderr);
#endif

	auth2_record_info(authctxt,
	    "client user \"%.100s\", client host \"%.100s\"", cuser, chost);

	/* test for allowed key and correct signature */
	authenticated = 0;
	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
	    PRIVSEP(sshkey_verify(key, sig, slen,
	    sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0)
		authenticated = 1;

	auth2_record_key(authctxt, authenticated, key);
	sshbuf_free(b);
done:
	debug2("%s: authenticated %d", __func__, authenticated);
	sshkey_free(key);
	free(pkalg);
	free(pkblob);
	free(cuser);
	free(chost);
	free(sig);
	return authenticated;
}
Esempio n. 10
0
static int
input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh)
{
	struct authctxt *authctxt = ssh->authctxt;
	struct kbdintctxt *kbdintctxt;
	int authenticated = 0, res;
	int r;
	u_int i, nresp;
	const char *devicename = NULL;
	char **response = NULL;

	if (authctxt == NULL)
		fatal("input_userauth_info_response: no authctxt");
	kbdintctxt = authctxt->kbdintctxt;
	if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL)
		fatal("input_userauth_info_response: no kbdintctxt");
	if (kbdintctxt->device == NULL)
		fatal("input_userauth_info_response: no device");

	authctxt->postponed = 0;	/* reset */
	if ((r = sshpkt_get_u32(ssh, &nresp)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));
	if (nresp != kbdintctxt->nreq)
		fatal("input_userauth_info_response: wrong number of replies");
	if (nresp > 100)
		fatal("input_userauth_info_response: too many replies");
	if (nresp > 0) {
		response = xcalloc(nresp, sizeof(char *));
		for (i = 0; i < nresp; i++)
			if ((r = sshpkt_get_cstring(ssh, &response[i],
			    NULL)) != 0)
				fatal("%s: %s", __func__, ssh_err(r));
	}
	if ((r = sshpkt_get_end(ssh)) != 0)
		fatal("%s: %s", __func__, ssh_err(r));

	res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);

	for (i = 0; i < nresp; i++) {
		explicit_bzero(response[i], strlen(response[i]));
		free(response[i]);
	}
	free(response);

	switch (res) {
	case 0:
		/* Success! */
		authenticated = authctxt->valid ? 1 : 0;
		break;
	case 1:
		/* Authentication needs further interaction */
		if (send_userauth_info_request(ssh) == 1)
			authctxt->postponed = 1;
		break;
	default:
		/* Failure! */
		break;
	}
	devicename = kbdintctxt->device->name;
	if (!authctxt->postponed) {
		if (authenticated) {
			auth2_challenge_stop(ssh);
		} else {
			/* start next device */
			/* may set authctxt->postponed */
			auth2_challenge_start(ssh);
		}
	}
	userauth_finish(ssh, authenticated, "keyboard-interactive",
	    devicename);
	return 0;
}
Esempio n. 11
0
static int
server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
{
	char *rtype = NULL;
	u_char want_reply;
	int r, success = 0, allocated_listen_port = 0;
	struct sshbuf *resp = NULL;

	if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
	    (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
		goto out;
	debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);

	/* -R style forwarding */
	if (strcmp(rtype, "tcpip-forward") == 0) {
		struct authctxt *authctxt = ssh->authctxt;
		struct Forward fwd;

		if (authctxt->pw == NULL || !authctxt->valid)
			fatal("server_input_global_request: no/invalid user");
		memset(&fwd, 0, sizeof(fwd));
		if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
		    (r = sshpkt_get_u32(ssh, &fwd.listen_port)) != 0)
			goto out;
		debug("server_input_global_request: tcpip-forward listen %s port %d",
		    fwd.listen_host, fwd.listen_port);

		/* check permissions */
		if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
		    no_port_forwarding_flag ||
		    (!want_reply && fwd.listen_port == 0) ||
		    (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED &&
		    authctxt->pw->pw_uid != 0)) {
			success = 0;
			ssh_packet_send_debug(ssh,
			    "Server has disabled port forwarding.");
		} else {
			/* Start listening on the port */
			success = channel_setup_remote_fwd_listener(ssh, &fwd,
			    &allocated_listen_port, &options.fwd_opts);
		}
		free(fwd.listen_host);
		if ((resp = sshbuf_new()) == NULL)
			fatal("%s: sshbuf_new", __func__);
		if (allocated_listen_port != 0 &&
		    (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
			fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r));
	} else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
		struct Forward fwd;

		memset(&fwd, 0, sizeof(fwd));
		if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
		    (r = sshpkt_get_u32(ssh, &fwd.listen_port)) != 0)
			goto out;
		debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
		    fwd.listen_host, fwd.listen_port);

		success = channel_cancel_rport_listener(&fwd);
		free(fwd.listen_host);
	} else if (strcmp(rtype, "*****@*****.**") == 0) {
		struct Forward fwd;

		memset(&fwd, 0, sizeof(fwd));
		if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
			goto out;
		debug("server_input_global_request: streamlocal-forward listen path %s",
		    fwd.listen_path);

		/* check permissions */
		if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
		    || no_port_forwarding_flag) {
			success = 0;
			ssh_packet_send_debug(ssh, "Server has disabled port forwarding.");
		} else {
			/* Start listening on the socket */
			success = channel_setup_remote_fwd_listener(ssh,
			    &fwd, NULL, &options.fwd_opts);
		}
		free(fwd.listen_path);
	} else if (strcmp(rtype, "*****@*****.**") == 0) {
		struct Forward fwd;

		memset(&fwd, 0, sizeof(fwd));
		if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
			goto out;
		debug("%s: cancel-streamlocal-forward path %s", __func__,
		    fwd.listen_path);

		success = channel_cancel_rport_listener(&fwd);
		free(fwd.listen_path);
	} else if (strcmp(rtype, "*****@*****.**") == 0) {
		no_more_sessions = 1;
		success = 1;
	} else if (strcmp(rtype, "*****@*****.**") == 0) {
		success = server_input_hostkeys_prove(&resp);
	}
	if (want_reply) {
		if ((r = sshpkt_start(ssh, success ?
		    SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 ||
		    (success && resp != NULL &&
		    (r = sshpkt_put(ssh, sshbuf_ptr(resp), sshbuf_len(resp)))
		    != 0) ||
		    (r = sshpkt_send(ssh)) != 0) 
			goto out;
		ssh_packet_write_wait(ssh);
	}
	r = 0;
 out:
	free(rtype);
	sshbuf_free(resp);
	return r;
}