コード例 #1
0
static int
deserialise_array(struct sshbuf *m, char ***ap, size_t *np)
{
	char **a = NULL;
	size_t i, n = 0;
	struct sshbuf *b = NULL;
	u_int tmp;
	int r = SSH_ERR_INTERNAL_ERROR;

	if ((r = sshbuf_get_u32(m, &tmp)) != 0 ||
	    (r = sshbuf_froms(m, &b)) != 0)
		goto out;
	if (tmp > INT_MAX) {
		r = SSH_ERR_INVALID_FORMAT;
		goto out;
	}
	n = tmp;
	if (n > 0 && (a = calloc(n, sizeof(*a))) == NULL) {
		r = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	for (i = 0; i < n; i++) {
		if ((r = sshbuf_get_cstring(b, &a[i], NULL)) != 0)
			goto out;
	}
	/* success */
	r = 0;
	*ap = a;
	a = NULL;
	*np = n;
	n = 0;
 out:
	for (i = 0; i < n; i++)
		free(a[i]);
	free(a);
	sshbuf_free(b);
	return r;
}
コード例 #2
0
ファイル: auth-options.c プロジェクト: 2trill2spill/freebsd
static int
parse_option_list(struct sshbuf *oblob, struct passwd *pw,
    u_int which, int crit,
    int *cert_no_port_forwarding_flag,
    int *cert_no_agent_forwarding_flag,
    int *cert_no_x11_forwarding_flag,
    int *cert_no_pty_flag,
    int *cert_no_user_rc,
    char **cert_forced_command,
    int *cert_source_address_done)
{
	struct ssh *ssh = active_state;		/* XXX */
	char *command, *allowed;
	const char *remote_ip;
	char *name = NULL;
	struct sshbuf *c = NULL, *data = NULL;
	int r, ret = -1, result, found;

	if ((c = sshbuf_fromb(oblob)) == NULL) {
		error("%s: sshbuf_fromb failed", __func__);
		goto out;
	}

	while (sshbuf_len(c) > 0) {
		sshbuf_free(data);
		data = NULL;
		if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 ||
		    (r = sshbuf_froms(c, &data)) != 0) {
			error("Unable to parse certificate options: %s",
			    ssh_err(r));
			goto out;
		}
		debug3("found certificate option \"%.100s\" len %zu",
		    name, sshbuf_len(data));
		found = 0;
		if ((which & OPTIONS_EXTENSIONS) != 0) {
			if (strcmp(name, "permit-X11-forwarding") == 0) {
				*cert_no_x11_forwarding_flag = 0;
				found = 1;
			} else if (strcmp(name,
			    "permit-agent-forwarding") == 0) {
				*cert_no_agent_forwarding_flag = 0;
				found = 1;
			} else if (strcmp(name,
			    "permit-port-forwarding") == 0) {
				*cert_no_port_forwarding_flag = 0;
				found = 1;
			} else if (strcmp(name, "permit-pty") == 0) {
				*cert_no_pty_flag = 0;
				found = 1;
			} else if (strcmp(name, "permit-user-rc") == 0) {
				*cert_no_user_rc = 0;
				found = 1;
			}
		}
		if (!found && (which & OPTIONS_CRITICAL) != 0) {
			if (strcmp(name, "force-command") == 0) {
				if ((r = sshbuf_get_cstring(data, &command,
				    NULL)) != 0) {
					error("Unable to parse \"%s\" "
					    "section: %s", name, ssh_err(r));
					goto out;
				}
				if (*cert_forced_command != NULL) {
					error("Certificate has multiple "
					    "force-command options");
					free(command);
					goto out;
				}
				*cert_forced_command = command;
				found = 1;
			}
			if (strcmp(name, "source-address") == 0) {
				if ((r = sshbuf_get_cstring(data, &allowed,
				    NULL)) != 0) {
					error("Unable to parse \"%s\" "
					    "section: %s", name, ssh_err(r));
					goto out;
				}
				if ((*cert_source_address_done)++) {
					error("Certificate has multiple "
					    "source-address options");
					free(allowed);
					goto out;
				}
				remote_ip = ssh_remote_ipaddr(ssh);
				result = addr_match_cidr_list(remote_ip,
				    allowed);
				free(allowed);
				switch (result) {
				case 1:
					/* accepted */
					break;
				case 0:
					/* no match */
					logit("Authentication tried for %.100s "
					    "with valid certificate but not "
					    "from a permitted host "
					    "(ip=%.200s).", pw->pw_name,
					    remote_ip);
					auth_debug_add("Your address '%.200s' "
					    "is not permitted to use this "
					    "certificate for login.",
					    remote_ip);
					goto out;
				case -1:
				default:
					error("Certificate source-address "
					    "contents invalid");
					goto out;
				}
				found = 1;
			}
		}

		if (!found) {
			if (crit) {
				error("Certificate critical option \"%s\" "
				    "is not supported", name);
				goto out;
			} else {
				logit("Certificate extension \"%s\" "
				    "is not supported", name);
			}
		} else if (sshbuf_len(data) != 0) {
			error("Certificate option \"%s\" corrupt "
			    "(extra data)", name);
			goto out;
		}
		free(name);
		name = NULL;
	}
	/* successfully parsed all options */
	ret = 0;

 out:
	if (ret != 0 &&
	    cert_forced_command != NULL &&
	    *cert_forced_command != NULL) {
		free(*cert_forced_command);
		*cert_forced_command = NULL;
	}
	free(name);
	sshbuf_free(data);
	sshbuf_free(c);
	return ret;
}
コード例 #3
0
ファイル: ssh-ecdsa.c プロジェクト: 0x0mar/backdoored-ssh
/* ARGSUSED */
int
ssh_ecdsa_verify(const struct sshkey *key,
    const u_char *signature, size_t signaturelen,
    const u_char *data, size_t datalen, u_int compat)
{
	ECDSA_SIG *sig = NULL;
	int hash_alg;
	u_char digest[SSH_DIGEST_MAX_LENGTH];
	size_t dlen;
	int ret = SSH_ERR_INTERNAL_ERROR;
	struct sshbuf *b = NULL, *sigbuf = NULL;
	char *ktype = NULL;

	if (key == NULL || key->ecdsa == NULL ||
	    sshkey_type_plain(key->type) != KEY_ECDSA)
		return SSH_ERR_INVALID_ARGUMENT;

	if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
	    (dlen = ssh_digest_bytes(hash_alg)) == 0)
		return SSH_ERR_INTERNAL_ERROR;

	/* fetch signature */
	if ((b = sshbuf_from(signature, signaturelen)) == NULL)
		return SSH_ERR_ALLOC_FAIL;
	if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
	    sshbuf_froms(b, &sigbuf) != 0) {
		ret = SSH_ERR_INVALID_FORMAT;
		goto out;
	}
	if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) {
		ret = SSH_ERR_KEY_TYPE_MISMATCH;
		goto out;
	}
	if (sshbuf_len(b) != 0) {
		ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
		goto out;
	}

	/* parse signature */
	if ((sig = ECDSA_SIG_new()) == NULL) {
		ret = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 ||
	    sshbuf_get_bignum2(sigbuf, sig->s) != 0) {
		ret = SSH_ERR_INVALID_FORMAT;
		goto out;
	}
	if (sshbuf_len(sigbuf) != 0) {
		ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
		goto out;
	}
	if ((ret = ssh_digest_memory(hash_alg, data, datalen,
	    digest, sizeof(digest))) != 0)
		goto out;

	switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) {
	case 1:
		ret = 0;
		break;
	case 0:
		ret = SSH_ERR_SIGNATURE_INVALID;
		goto out;
	default:
		ret = SSH_ERR_LIBCRYPTO_ERROR;
		goto out;
	}

 out:
	explicit_bzero(digest, sizeof(digest));
	if (sigbuf != NULL)
		sshbuf_free(sigbuf);
	if (b != NULL)
		sshbuf_free(b);
	if (sig != NULL)
		ECDSA_SIG_free(sig);
	free(ktype);
	return ret;
}
コード例 #4
0
static int
cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
    u_int which, int crit)
{
	char *command, *allowed;
	char *name = NULL;
	struct sshbuf *c = NULL, *data = NULL;
	int r, ret = -1, found;

	if ((c = sshbuf_fromb(oblob)) == NULL) {
		error("%s: sshbuf_fromb failed", __func__);
		goto out;
	}

	while (sshbuf_len(c) > 0) {
		sshbuf_free(data);
		data = NULL;
		if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 ||
		    (r = sshbuf_froms(c, &data)) != 0) {
			error("Unable to parse certificate options: %s",
			    ssh_err(r));
			goto out;
		}
		debug3("found certificate option \"%.100s\" len %zu",
		    name, sshbuf_len(data));
		found = 0;
		if ((which & OPTIONS_EXTENSIONS) != 0) {
			if (strcmp(name, "permit-X11-forwarding") == 0) {
				opts->permit_x11_forwarding_flag = 1;
				found = 1;
			} else if (strcmp(name,
			    "permit-agent-forwarding") == 0) {
				opts->permit_agent_forwarding_flag = 1;
				found = 1;
			} else if (strcmp(name,
			    "permit-port-forwarding") == 0) {
				opts->permit_port_forwarding_flag = 1;
				found = 1;
			} else if (strcmp(name, "permit-pty") == 0) {
				opts->permit_pty_flag = 1;
				found = 1;
			} else if (strcmp(name, "permit-user-rc") == 0) {
				opts->permit_user_rc = 1;
				found = 1;
			}
		}
		if (!found && (which & OPTIONS_CRITICAL) != 0) {
			if (strcmp(name, "force-command") == 0) {
				if ((r = sshbuf_get_cstring(data, &command,
				    NULL)) != 0) {
					error("Unable to parse \"%s\" "
					    "section: %s", name, ssh_err(r));
					goto out;
				}
				if (opts->force_command != NULL) {
					error("Certificate has multiple "
					    "force-command options");
					free(command);
					goto out;
				}
				opts->force_command = command;
				found = 1;
			}
			if (strcmp(name, "source-address") == 0) {
				if ((r = sshbuf_get_cstring(data, &allowed,
				    NULL)) != 0) {
					error("Unable to parse \"%s\" "
					    "section: %s", name, ssh_err(r));
					goto out;
				}
				if (opts->required_from_host_cert != NULL) {
					error("Certificate has multiple "
					    "source-address options");
					free(allowed);
					goto out;
				}
				/* Check syntax */
				if (addr_match_cidr_list(NULL, allowed) == -1) {
					error("Certificate source-address "
					    "contents invalid");
					goto out;
				}
				opts->required_from_host_cert = allowed;
				found = 1;
			}
		}

		if (!found) {
			if (crit) {
				error("Certificate critical option \"%s\" "
				    "is not supported", name);
				goto out;
			} else {
				logit("Certificate extension \"%s\" "
				    "is not supported", name);
			}
		} else if (sshbuf_len(data) != 0) {
			error("Certificate option \"%s\" corrupt "
			    "(extra data)", name);
			goto out;
		}
		free(name);
		name = NULL;
	}
	/* successfully parsed all options */
	ret = 0;

 out:
	free(name);
	sshbuf_free(data);
	sshbuf_free(c);
	return ret;
}