static int
host_delete(struct hostkey_foreach_line *l, void *_ctx)
{
	struct host_delete_ctx *ctx = (struct host_delete_ctx *)_ctx;
	int loglevel = ctx->quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE;
	size_t i;

	if (l->status == HKF_STATUS_MATCHED) {
		if (l->marker != MRK_NONE) {
			/* Don't remove CA and revocation lines */
			fprintf(ctx->out, "%s\n", l->line);
			return 0;
		}

		/* XXX might need a knob for this later */
		/* Don't remove RSA1 keys */
		if (l->key->type == KEY_RSA1) {
			fprintf(ctx->out, "%s\n", l->line);
			return 0;
		}

		/*
		 * If this line contains one of the keys that we will be
		 * adding later, then don't change it and mark the key for
		 * skipping.
		 */
		for (i = 0; i < ctx->nkeys; i++) {
			if (sshkey_equal(ctx->keys[i], l->key)) {
				ctx->skip_keys[i] = 1;
				fprintf(ctx->out, "%s\n", l->line);
				debug3("%s: %s key already at %s:%ld", __func__,
				    sshkey_type(l->key), l->path, l->linenum);
				return 0;
			}
		}

		/*
		 * Hostname matches and has no CA/revoke marker, delete it
		 * by *not* writing the line to ctx->out.
		 */
		do_log2(loglevel, "%s%s%s:%ld: Removed %s key for host %s",
		    ctx->quiet ? __func__ : "", ctx->quiet ? ": " : "",
		    l->path, l->linenum, sshkey_type(l->key), ctx->host);
		ctx->modified = 1;
		return 0;
	}
	/* Retain non-matching hosts and invalid lines when deleting */
	if (l->status == HKF_STATUS_INVALID) {
		do_log2(loglevel, "%s%s%s:%ld: invalid known_hosts entry",
		    ctx->quiet ? __func__ : "", ctx->quiet ? ": " : "",
		    l->path, l->linenum);
	}
	fprintf(ctx->out, "%s\n", l->line);
	return 0;
}
Beispiel #2
0
static int
monitor_read_log(struct monitor *pmonitor)
{
	struct sshbuf *logmsg;
	u_int len, level;
	u_char *p;
	char *msg;
	int r;

	if ((logmsg = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);

	/* Read length */
	if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) {
		if (errno == EPIPE) {
			sshbuf_free(logmsg);
			debug("%s: child log fd closed", __func__);
			close(pmonitor->m_log_recvfd);
			pmonitor->m_log_recvfd = -1;
			return -1;
		}
		fatal("%s: log fd read: %s", __func__, strerror(errno));
	}
	if ((r = sshbuf_get_u32(logmsg, &len)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	if (len <= 4 || len > 8192)
		fatal("%s: invalid log message length %u", __func__, len);

	/* Read severity, message */
	sshbuf_reset(logmsg);
	if ((r = sshbuf_reserve(logmsg, len, &p)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len)
		fatal("%s: log fd read: %s", __func__, strerror(errno));

	/* Log it */
	if ((r = sshbuf_get_u32(logmsg, &level)) != 0 ||
	    (r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	if (log_level_name(level) == NULL)
		fatal("%s: invalid log level %u (corrupted message?)",
		    __func__, level);
	do_log2(level, "%s [preauth]", msg);

	sshbuf_free(logmsg);
	free(msg);

	return 0;
}
Beispiel #3
0
static int
monitor_read_log(struct monitor *pmonitor)
{
	Buffer logmsg;
	u_int len, level;
	char *msg;

	buffer_init(&logmsg);

	/* Read length */
	buffer_append_space(&logmsg, 4);
	if (atomicio(read, pmonitor->m_log_recvfd,
	    buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) {
		if (errno == EPIPE) {
			buffer_free(&logmsg);
			debug("%s: child log fd closed", __func__);
			close(pmonitor->m_log_recvfd);
			pmonitor->m_log_recvfd = -1;
			return -1;
		}
		fatal("%s: log fd read: %s", __func__, strerror(errno));
	}
	len = buffer_get_int(&logmsg);
	if (len <= 4 || len > 8192)
		fatal("%s: invalid log message length %u", __func__, len);

	/* Read severity, message */
	buffer_clear(&logmsg);
	buffer_append_space(&logmsg, len);
	if (atomicio(read, pmonitor->m_log_recvfd,
	    buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg))
		fatal("%s: log fd read: %s", __func__, strerror(errno));

	/* Log it */
	level = buffer_get_int(&logmsg);
	msg = buffer_get_string(&logmsg, NULL);
	if (log_level_name(level) == NULL)
		fatal("%s: invalid log level %u (corrupted message?)",
		    __func__, level);
	do_log2(level, "%s [preauth]", msg);

	buffer_free(&logmsg);
	free(msg);

	return 0;
}
int
hostfile_replace_entries(const char *filename, const char *host, const char *ip,
    struct sshkey **keys, size_t nkeys, int store_hash, int quiet, int hash_alg)
{
	int r, fd, oerrno = 0;
	int loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE;
	struct host_delete_ctx ctx;
	char *fp, *temp = NULL, *back = NULL;
	mode_t omask;
	size_t i;

	omask = umask(077);

	memset(&ctx, 0, sizeof(ctx));
	ctx.host = host;
	ctx.quiet = quiet;
	if ((ctx.skip_keys = calloc(nkeys, sizeof(*ctx.skip_keys))) == NULL)
		return SSH_ERR_ALLOC_FAIL;
	ctx.keys = keys;
	ctx.nkeys = nkeys;
	ctx.modified = 0;

	/*
	 * Prepare temporary file for in-place deletion.
	 */
	if ((r = asprintf(&temp, "%s.XXXXXXXXXXX", filename)) < 0 ||
	    (r = asprintf(&back, "%s.old", filename)) < 0) {
		r = SSH_ERR_ALLOC_FAIL;
		goto fail;
	}

	if ((fd = mkstemp(temp)) == -1) {
		oerrno = errno;
		error("%s: mkstemp: %s", __func__, strerror(oerrno));
		r = SSH_ERR_SYSTEM_ERROR;
		goto fail;
	}
	if ((ctx.out = fdopen(fd, "w")) == NULL) {
		oerrno = errno;
		close(fd);
		error("%s: fdopen: %s", __func__, strerror(oerrno));
		r = SSH_ERR_SYSTEM_ERROR;
		goto fail;
	}

	/* Remove all entries for the specified host from the file */
	if ((r = hostkeys_foreach(filename, host_delete, &ctx, host, ip,
	    HKF_WANT_PARSE_KEY)) != 0) {
		error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
		goto fail;
	}

	/* Add the requested keys */
	for (i = 0; i < nkeys; i++) {
		if (ctx.skip_keys[i])
			continue;
		if ((fp = sshkey_fingerprint(keys[i], hash_alg,
		    SSH_FP_DEFAULT)) == NULL) {
			r = SSH_ERR_ALLOC_FAIL;
			goto fail;
		}
		do_log2(loglevel, "%s%sAdding new key for %s to %s: %s %s",
		    quiet ? __func__ : "", quiet ? ": " : "", host, filename,
		    sshkey_ssh_name(keys[i]), fp);
		free(fp);
		if (!write_host_entry(ctx.out, host, ip, keys[i], store_hash)) {
			r = SSH_ERR_INTERNAL_ERROR;
			goto fail;
		}
		ctx.modified = 1;
	}
	fclose(ctx.out);
	ctx.out = NULL;

	if (ctx.modified) {
		/* Backup the original file and replace it with the temporary */
		if (unlink(back) == -1 && errno != ENOENT) {
			oerrno = errno;
			error("%s: unlink %.100s: %s", __func__,
			    back, strerror(errno));
			r = SSH_ERR_SYSTEM_ERROR;
			goto fail;
		}
		if (link(filename, back) == -1) {
			oerrno = errno;
			error("%s: link %.100s to %.100s: %s", __func__,
			    filename, back, strerror(errno));
			r = SSH_ERR_SYSTEM_ERROR;
			goto fail;
		}
		if (rename(temp, filename) == -1) {
			oerrno = errno;
			error("%s: rename \"%s\" to \"%s\": %s", __func__,
			    temp, filename, strerror(errno));
			r = SSH_ERR_SYSTEM_ERROR;
			goto fail;
		}
	} else {
		/* No changes made; just delete the temporary file */
		if (unlink(temp) != 0)
			error("%s: unlink \"%s\": %s", __func__,
			    temp, strerror(errno));
	}

	/* success */
	r = 0;
 fail:
	if (temp != NULL && r != 0)
		unlink(temp);
	free(temp);
	free(back);
	if (ctx.out != NULL)
		fclose(ctx.out);
	free(ctx.skip_keys);
	umask(omask);
	if (r == SSH_ERR_SYSTEM_ERROR)
		errno = oerrno;
	return r;
}
Beispiel #5
0
void
auth_log(Authctxt *authctxt, int authenticated, int partial,
    const char *method, const char *submethod)
{
	struct ssh *ssh = active_state; /* XXX */
	int level = SYSLOG_LEVEL_VERBOSE;
	const char *authmsg;
	char *extra = NULL;

	if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
		return;

	/* Raise logging level */
	if (authenticated == 1 ||
	    !authctxt->valid ||
	    authctxt->failures >= options.max_authtries / 2 ||
	    strcmp(method, "password") == 0)
		level = SYSLOG_LEVEL_INFO;

	if (authctxt->postponed)
		authmsg = "Postponed";
	else if (partial)
		authmsg = "Partial";
	else
		authmsg = authenticated ? "Accepted" : "Failed";

	if ((extra = format_method_key(authctxt)) == NULL) {
		if (authctxt->auth_method_info != NULL)
			extra = xstrdup(authctxt->auth_method_info);
	}

	do_log2(level, "%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
	    authmsg,
	    method,
	    submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
	    authctxt->valid ? "" : "invalid user ",
	    authctxt->user,
	    ssh_remote_ipaddr(ssh),
	    ssh_remote_port(ssh),
	    extra != NULL ? ": " : "",
	    extra != NULL ? extra : "");

	free(extra);

#ifdef CUSTOM_FAILED_LOGIN
	if (authenticated == 0 && !authctxt->postponed &&
	    (strcmp(method, "password") == 0 ||
	    strncmp(method, "keyboard-interactive", 20) == 0 ||
	    strcmp(method, "challenge-response") == 0))
		record_failed_login(authctxt->user,
		    auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
# ifdef WITH_AIXAUTHENTICATE
	if (authenticated)
		sys_auth_record_login(authctxt->user,
		    auth_get_canonical_hostname(ssh, options.use_dns), "ssh",
		    &loginmsg);
# endif
#endif
#ifdef SSH_AUDIT_EVENTS
	if (authenticated == 0 && !authctxt->postponed)
		audit_event(audit_classify_auth(method));
#endif
}