Commit message: - (djm) Merge FreeBSD PAM code: replaces PAM password auth kludge with
   proper challenge-response module
CVE: CVE-2015-6563
Vulnerability description: The monitor component in sshd in OpenSSH before 7.0 on non-OpenBSD platforms accepts extraneous username data in MONITOR_REQ_PAM_INIT_CTX requests, which allows local users to conduct impersonation attacks by leveraging any SSH login access in conjunction with control of the sshd uid to send a crafted MONITOR_REQ_PWNAM request, related to monitor.c and monitor_wrap.c.

Project: openssh-portable

mm_get_kex(Buffer *m)
{
	Kex *kex;
	void *blob;
	u_int bloblen;

	kex = xmalloc(sizeof(*kex));
	memset(kex, 0, sizeof(*kex));
	kex->session_id = buffer_get_string(m, &kex->session_id_len);
	if ((session_id2 == NULL) ||
	    (kex->session_id_len != session_id2_len) ||
	    (memcmp(kex->session_id, session_id2, session_id2_len) != 0))
		fatal("mm_get_get: internal error: bad session id");
	kex->we_need = buffer_get_int(m);
	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
	kex->server = 1;
	kex->hostkey_type = buffer_get_int(m);
	kex->kex_type = buffer_get_int(m);
	blob = buffer_get_string(m, &bloblen);
	buffer_init(&kex->my);
	buffer_append(&kex->my, blob, bloblen);
	xfree(blob);
	blob = buffer_get_string(m, &bloblen);
	buffer_init(&kex->peer);
	buffer_append(&kex->peer, blob, bloblen);
	xfree(blob);
	kex->done = 1;
	kex->flags = buffer_get_int(m);
	kex->client_version_string = buffer_get_string(m, NULL);
	kex->server_version_string = buffer_get_string(m, NULL);
	kex->load_host_key=&get_hostkey_by_type;
	kex->host_key_index=&get_hostkey_index;

	return (kex);
}

Project: openssh-portable

mm_answer_pam_start(int socket, Buffer *m)
{
	char *user;
	
	user = buffer_get_string(m, NULL);

	start_pam(user);

	xfree(user);

	return (0);
}

Project: openssh-portable

mm_answer_pty_cleanup(int socket, Buffer *m)
{
	Session *s;
	char *tty;

	debug3("%s entering", __func__);

	tty = buffer_get_string(m, NULL);
	if ((s = session_by_tty(tty)) != NULL)
		mm_session_close(s);
	buffer_clear(m);
	xfree(tty);
	return (0);
}

Project: openssh-portable

sshpam_init_ctx(Authctxt *authctxt)
{
	struct pam_ctxt *ctxt;
	int socks[2];

	/* Initialize PAM */
	if (sshpam_init(authctxt->user) == -1) {
		error("PAM: initialization failed");
		return (NULL);
	}

	ctxt = xmalloc(sizeof *ctxt);
	ctxt->pam_done = 0;

	/* Start the authentication thread */
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
		error("PAM: failed create sockets: %s", strerror(errno));
		xfree(ctxt);
		return (NULL);
	}
	ctxt->pam_psock = socks[0];
	ctxt->pam_csock = socks[1];
	if (pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt) == -1) {
		error("PAM: failed to start authentication thread: %s",
		    strerror(errno));
		close(socks[0]);
		close(socks[1]);
		xfree(ctxt);
		return (NULL);
	}
	fatal_add_cleanup(sshpam_thread_cleanup, ctxt);
	return (ctxt);
}

Project: openssh-portable

monitor_valid_userblob(u_char *data, u_int datalen)
{
	Buffer b;
	char *p;
	u_int len;
	int fail = 0;

	buffer_init(&b);
	buffer_append(&b, data, datalen);

	if (datafellows & SSH_OLD_SESSIONID) {
		p = buffer_ptr(&b);
		len = buffer_len(&b);
		if ((session_id2 == NULL) ||
		    (len < session_id2_len) ||
		    (memcmp(p, session_id2, session_id2_len) != 0))
			fail++;
		buffer_consume(&b, session_id2_len);
	} else {
		p = buffer_get_string(&b, &len);
		if ((session_id2 == NULL) ||
		    (len != session_id2_len) ||
		    (memcmp(p, session_id2, session_id2_len) != 0))
			fail++;
		xfree(p);
	}
	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
		fail++;
	p = buffer_get_string(&b, NULL);
	if (strcmp(authctxt->user, p) != 0) {
		logit("wrong user name passed to monitor: expected %s != %.100s",
		    authctxt->user, p);
		fail++;
	}
	xfree(p);
	buffer_skip_string(&b);
	if (datafellows & SSH_BUG_PKAUTH) {
		if (!buffer_get_char(&b))
			fail++;
	} else {
		p = buffer_get_string(&b, NULL);
		if (strcmp("publickey", p) != 0)
			fail++;
		xfree(p);
		if (!buffer_get_char(&b))
			fail++;
		buffer_skip_string(&b);
	}
	buffer_skip_string(&b);
	if (buffer_len(&b) != 0)
		fail++;
	buffer_free(&b);
	return (fail == 0);
}

Project: openssh-portable

mm_answer_keyverify(int socket, Buffer *m)
{
	Key *key;
	u_char *signature, *data, *blob;
	u_int signaturelen, datalen, bloblen;
	int verified = 0;
	int valid_data = 0;

	blob = buffer_get_string(m, &bloblen);
	signature = buffer_get_string(m, &signaturelen);
	data = buffer_get_string(m, &datalen);

	if (hostbased_cuser == NULL || hostbased_chost == NULL ||
	  !monitor_allowed_key(blob, bloblen))
		fatal("%s: bad key, not previously allowed", __func__);

	key = key_from_blob(blob, bloblen);
	if (key == NULL)
		fatal("%s: bad public key blob", __func__);

	switch (key_blobtype) {
	case MM_USERKEY:
		valid_data = monitor_valid_userblob(data, datalen);
		break;
	case MM_HOSTKEY:
		valid_data = monitor_valid_hostbasedblob(data, datalen,
		    hostbased_cuser, hostbased_chost);
		break;
	default:
		valid_data = 0;
		break;
	}
	if (!valid_data)
		fatal("%s: bad signature data blob", __func__);

	verified = key_verify(key, signature, signaturelen, data, datalen);
	debug3("%s: key %p signature %s",
	    __func__, key, verified ? "verified" : "unverified");

	key_free(key);
	xfree(blob);
	xfree(signature);
	xfree(data);

	auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";

	monitor_reset_key_state();

	buffer_clear(m);
	buffer_put_int(m, verified);
	mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m);

	return (verified);
}

Project: openssh-portable

sshpam_respond(void *ctx, u_int num, char **resp)
{
	Buffer buffer;
	struct pam_ctxt *ctxt = ctx;

	debug2("PAM: %s", __func__);
	switch (ctxt->pam_done) {
	case 1:
		sshpam_authenticated = 1;
		return (0);
	case 0:
		break;
	default:
		return (-1);
	}
	if (num != 1) {
		error("PAM: expected one response, got %u", num);
		return (-1);
	}
	buffer_init(&buffer);
	buffer_put_cstring(&buffer, *resp);
	ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer);
	buffer_free(&buffer);
	return (1);
}

Project: openssh-portable

mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
{
	Buffer b;
	int len;
	Enc *enc;
	Mac *mac;
	Comp *comp;
	Newkeys *newkey = newkeys[mode];

	debug3("%s: converting %p", __func__, newkey);

	if (newkey == NULL) {
		error("%s: newkey == NULL", __func__);
		return 0;
	}
	enc = &newkey->enc;
	mac = &newkey->mac;
	comp = &newkey->comp;

	buffer_init(&b);
	/* Enc structure */
	buffer_put_cstring(&b, enc->name);
	/* The cipher struct is constant and shared, you export pointer */
	buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
	buffer_put_int(&b, enc->enabled);
	buffer_put_int(&b, enc->block_size);
	buffer_put_string(&b, enc->key, enc->key_len);
	packet_get_keyiv(mode, enc->iv, enc->block_size);
	buffer_put_string(&b, enc->iv, enc->block_size);

	/* Mac structure */
	buffer_put_cstring(&b, mac->name);
	buffer_put_int(&b, mac->enabled);
	buffer_put_string(&b, mac->key, mac->key_len);

	/* Comp structure */
	buffer_put_int(&b, comp->type);
	buffer_put_int(&b, comp->enabled);
	buffer_put_cstring(&b, comp->name);

	len = buffer_len(&b);
	if (lenp != NULL)
		*lenp = len;
	if (blobp != NULL) {
		*blobp = xmalloc(len);
		memcpy(*blobp, buffer_ptr(&b), len);
	}
	memset(buffer_ptr(&b), 0, len);
	buffer_free(&b);
	return len;
}

Project: openssh-portable

monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
    char *chost)
{
	Buffer b;
	char *p;
	u_int len;
	int fail = 0;

	buffer_init(&b);
	buffer_append(&b, data, datalen);

	p = buffer_get_string(&b, &len);
	if ((session_id2 == NULL) ||
	    (len != session_id2_len) ||
	    (memcmp(p, session_id2, session_id2_len) != 0))
		fail++;
	xfree(p);

	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
		fail++;
	p = buffer_get_string(&b, NULL);
	if (strcmp(authctxt->user, p) != 0) {
		logit("wrong user name passed to monitor: expected %s != %.100s",
		    authctxt->user, p);
		fail++;
	}
	xfree(p);
	buffer_skip_string(&b);	/* service */
	p = buffer_get_string(&b, NULL);
	if (strcmp(p, "hostbased") != 0)
		fail++;
	xfree(p);
	buffer_skip_string(&b);	/* pkalg */
	buffer_skip_string(&b);	/* pkblob */

	/* verify client host, strip trailing dot if necessary */
	p = buffer_get_string(&b, NULL);
	if (((len = strlen(p)) > 0) && p[len - 1] == '.')
		p[len - 1] = '\0';
	if (strcmp(p, chost) != 0)
		fail++;
	xfree(p);

	/* verify client user */
	p = buffer_get_string(&b, NULL);
	if (strcmp(p, cuser) != 0)
		fail++;
	xfree(p);

	if (buffer_len(&b) != 0)
		fail++;
	buffer_free(&b);
	return (fail == 0);
}

Project: openssh-portable

sshpam_thread_cleanup(void *ctxtp)
{
	struct pam_ctxt *ctxt = ctxtp;

	pthread_cancel(ctxt->pam_thread);
	pthread_join(ctxt->pam_thread, NULL);
	close(ctxt->pam_psock);
	close(ctxt->pam_csock);
}

Project: openssh-portable

do_pam_session(const char *user, const char *tty)
{
	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, 
	    (const void *)&null_conv);
	if (sshpam_err != PAM_SUCCESS)
		fatal("PAM: failed to set PAM_CONV: %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	debug("PAM: setting PAM_TTY to \"%s\"", tty);
	sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, tty);
	if (sshpam_err != PAM_SUCCESS)
		fatal("PAM: failed to set PAM_TTY: %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	sshpam_err = pam_open_session(sshpam_handle, 0);
	if (sshpam_err != PAM_SUCCESS)
		fatal("PAM: pam_open_session(): %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	sshpam_session_open = 1;
}

Project: openssh-portable

mm_sshpam_respond(void *ctx, u_int num, char **resp)
{
	Buffer m;
	int i, ret;

	debug3("%s", __func__);
	buffer_init(&m);
	buffer_put_int(&m, num);
	for (i = 0; i < num; ++i)
		buffer_put_cstring(&m, resp[i]);
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
	debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
	ret = buffer_get_int(&m);
	debug3("%s: pam_respond returned %d", __func__, ret);
	buffer_free(&m);
	return (ret);
}

Project: openssh-portable

sshpam_query(void *ctx, char **name, char **info,
    u_int *num, char ***prompts, u_int **echo_on)
{
	Buffer buffer;
	struct pam_ctxt *ctxt = ctx;
	size_t plen;
	u_char type;
	char *msg;

	buffer_init(&buffer);
	*name = xstrdup("");
	*info = xstrdup("");
	*prompts = xmalloc(sizeof(char *));
	**prompts = NULL;
	plen = 0;
	*echo_on = xmalloc(sizeof(u_int));
	while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
		type = buffer_get_char(&buffer);
		msg = buffer_get_string(&buffer, NULL);
		switch (type) {
		case PAM_PROMPT_ECHO_ON:
		case PAM_PROMPT_ECHO_OFF:
			*num = 1;
			**prompts = xrealloc(**prompts, plen + strlen(msg) + 1);
			plen += sprintf(**prompts + plen, "%s", msg);
			**echo_on = (type == PAM_PROMPT_ECHO_ON);
			xfree(msg);
			return (0);
		case PAM_ERROR_MSG:
		case PAM_TEXT_INFO:
			/* accumulate messages */
			**prompts = xrealloc(**prompts, plen + strlen(msg) + 1);
			plen += sprintf(**prompts + plen, "%s", msg);
			xfree(msg);
			break;
		case PAM_NEW_AUTHTOK_REQD:
			sshpam_new_authtok_reqd = 1;
			/* FALLTHROUGH */
		case PAM_SUCCESS:
		case PAM_AUTH_ERR:
			if (**prompts != NULL) {
				/* drain any accumulated messages */
#if 0 /* XXX - not compatible with privsep */
				packet_start(SSH2_MSG_USERAUTH_BANNER);
				packet_put_cstring(**prompts);
				packet_put_cstring("");
				packet_send();
				packet_write_wait();
#endif
				xfree(**prompts);
				**prompts = NULL;
			}
			if (type == PAM_SUCCESS) {
				*num = 0;
				**echo_on = 0;
				ctxt->pam_done = 1;
				xfree(msg);
				return (0);
			}
			error("PAM: %s", msg);
		default:
			*num = 0;
			**echo_on = 0;
			xfree(msg);
			ctxt->pam_done = -1;
			return (-1);
		}
	}
	return (-1);
}

Project: openssh-portable

mm_answer_authpassword(int socket, Buffer *m)
{
	static int call_count;
	char *passwd;
	int authenticated;
	u_int plen;

	passwd = buffer_get_string(m, &plen);
	/* Only authenticate if the context is valid */
	authenticated = options.password_authentication &&
	    auth_password(authctxt, passwd) && authctxt->valid;
	memset(passwd, 0, strlen(passwd));
	xfree(passwd);

	buffer_clear(m);
	buffer_put_int(m, authenticated);

	debug3("%s: sending result %d", __func__, authenticated);
	mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m);

	call_count++;
	if (plen == 0 && call_count == 1)
		auth_method = "none";
	else
		auth_method = "password";

	/* Causes monitor loop to terminate if authenticated */
	return (authenticated);
}

Project: openssh-portable

print_pam_messages(void)
{
	/* XXX */
}

Project: openssh-portable

do_pam_account(const char *user, const char *ruser)
{
	/* XXX */
	return (1);
}

Project: openssh-portable

monitor_init(void)
{
	struct monitor *mon;
	int pair[2];

	mon = xmalloc(sizeof(*mon));

	monitor_socketpair(pair);

	mon->m_recvfd = pair[0];
	mon->m_sendfd = pair[1];

	/* Used to share zlib space across processes */
	if (options.compression) {
		mon->m_zback = mm_create(NULL, MM_MEMSIZE);
		mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);

		/* Compression needs to share state across borders */
		mm_init_compression(mon->m_zlib);
	}

	return mon;
}

Project: openssh-portable

mm_request_receive(int socket, Buffer *m)
{
	u_char buf[4];
	u_int msg_len;
	ssize_t res;

	debug3("%s entering", __func__);

	res = atomicio(read, socket, buf, sizeof(buf));
	if (res != sizeof(buf)) {
		if (res == 0)
			fatal_cleanup();
		fatal("%s: read: %ld", __func__, (long)res);
	}
	msg_len = GET_32BIT(buf);
	if (msg_len > 256 * 1024)
		fatal("%s: read: bad msg_len %d", __func__, msg_len);
	buffer_clear(m);
	buffer_append_space(m, msg_len);
	res = atomicio(read, socket, buffer_ptr(m), msg_len);
	if (res != msg_len)
		fatal("%s: read: %ld != msg_len", __func__, (long)res);
}

Project: openssh-portable

mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
{
	Buffer m;
	u_char *blob;
	u_int blen;
	int success = 0;

	debug3("%s entering", __func__);

	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
	if (key_to_blob(key, &blob, &blen) == 0)
		fatal("%s: key_to_blob failed", __func__);
	key->type = KEY_RSA1;

	buffer_init(&m);
	buffer_put_string(&m, blob, blen);
	buffer_put_string(&m, response, 16);
	xfree(blob);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);

	success = buffer_get_int(&m);
	buffer_free(&m);

	return (success);
}

Project: openssh-portable

mm_user_key_allowed(struct passwd *pw, Key *key)
{
	return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
}

Project: openssh-portable

monitor_reset_key_state(void)
{
	/* reset state */
	if (key_blob != NULL)
		xfree(key_blob);
	if (hostbased_cuser != NULL)
		xfree(hostbased_cuser);
	if (hostbased_chost != NULL)
		xfree(hostbased_chost);
	key_blob = NULL;
	key_bloblen = 0;
	key_blobtype = MM_NOKEY;
	hostbased_cuser = NULL;
	hostbased_chost = NULL;
}

Project: openssh-portable

mm_sshpam_query(void *ctx, char **name, char **info,
    u_int *num, char ***prompts, u_int **echo_on)
{
	Buffer m;
	int i, ret;

	debug3("%s", __func__);
	buffer_init(&m);
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
	debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
	ret = buffer_get_int(&m);
	debug3("%s: pam_query returned %d", __func__, ret);
	*name = buffer_get_string(&m, NULL);
	*info = buffer_get_string(&m, NULL);
	*num = buffer_get_int(&m);
	*prompts = xmalloc((*num + 1) * sizeof(char *));
	*echo_on = xmalloc((*num + 1) * sizeof(u_int));
	for (i = 0; i < *num; ++i) {
		(*prompts)[i] = buffer_get_string(&m, NULL);
		(*echo_on)[i] = buffer_get_int(&m);
	}
	buffer_free(&m);
	return (ret);
}

Project: openssh-portable

kbdint_reset_device(KbdintAuthctxt *kbdintctxt)
{
	if (kbdintctxt->ctxt) {
		kbdintctxt->device->free_ctx(kbdintctxt->ctxt);
		kbdintctxt->ctxt = NULL;
	}
	kbdintctxt->device = NULL;
}

Project: openssh-portable

finish_pam(void)
{
	fatal_remove_cleanup(sshpam_cleanup, NULL);
	sshpam_cleanup(NULL);
}

Project: openssh-portable

int mm_answer_auth2_read_banner(int socket, Buffer *m)
{
	char *banner;

	buffer_clear(m);
	banner = auth2_read_banner();
	buffer_put_cstring(m, banner != NULL ? banner : "");
	mm_request_send(socket, MONITOR_ANS_AUTH2_READ_BANNER, m);

	if (banner != NULL)
		xfree(banner);

	return (0);
}

Project: openssh-portable

mm_answer_krb4(int socket, Buffer *m)
{
	KTEXT_ST auth, reply;
	char  *client, *p;
	int success;
	u_int alen;

	reply.length = auth.length = 0;
 
	p = buffer_get_string(m, &alen);
	if (alen >=  MAX_KTXT_LEN)
		 fatal("%s: auth too large", __func__);
	memcpy(auth.dat, p, alen);
	auth.length = alen;
	memset(p, 0, alen);
	xfree(p);

	success = options.kerberos_authentication &&
	    authctxt->valid &&
	    auth_krb4(authctxt, &auth, &client, &reply);

	memset(auth.dat, 0, alen);
	buffer_clear(m);
	buffer_put_int(m, success);

	if (success) {
		buffer_put_cstring(m, client);
		buffer_put_string(m, reply.dat, reply.length);
		if (client)
			xfree(client);
		if (reply.length)
			memset(reply.dat, 0, reply.length);
	}

	debug3("%s: sending result %d", __func__, success);
	mm_request_send(socket, MONITOR_ANS_KRB4, m);

	auth_method = "kerberos";

	/* Causes monitor loop to terminate if authenticated */
	return (success);
}

Project: openssh-portable

mm_answer_keyallowed(int socket, Buffer *m)
{
	Key *key;
	char *cuser, *chost;
	u_char *blob;
	u_int bloblen;
	enum mm_keytype type = 0;
	int allowed = 0;

	debug3("%s entering", __func__);

	type = buffer_get_int(m);
	cuser = buffer_get_string(m, NULL);
	chost = buffer_get_string(m, NULL);
	blob = buffer_get_string(m, &bloblen);

	key = key_from_blob(blob, bloblen);

	if ((compat20 && type == MM_RSAHOSTKEY) ||
	    (!compat20 && type != MM_RSAHOSTKEY))
		fatal("%s: key type and protocol mismatch", __func__);

	debug3("%s: key_from_blob: %p", __func__, key);

	if (key != NULL && authctxt->pw != NULL) {
		switch(type) {
		case MM_USERKEY:
			allowed = options.pubkey_authentication &&
			    user_key_allowed(authctxt->pw, key);
			break;
		case MM_HOSTKEY:
			allowed = options.hostbased_authentication &&
			    hostbased_key_allowed(authctxt->pw,
			    cuser, chost, key);
			break;
		case MM_RSAHOSTKEY:
			key->type = KEY_RSA1; /* XXX */
			allowed = options.rhosts_rsa_authentication &&
			    auth_rhosts_rsa_key_allowed(authctxt->pw,
			    cuser, chost, key);
			break;
		default:
			fatal("%s: unknown key type %d", __func__, type);
			break;
		}
	}
	if (key != NULL)
		key_free(key);

	/* clear temporarily storage (used by verify) */
	monitor_reset_key_state();

	if (allowed) {
		/* Save temporarily for comparison in verify */
		key_blob = blob;
		key_bloblen = bloblen;
		key_blobtype = type;
		hostbased_cuser = cuser;
		hostbased_chost = chost;
	}

	debug3("%s: key %p is %s",
	    __func__, key, allowed ? "allowed" : "disallowed");

	buffer_clear(m);
	buffer_put_int(m, allowed);
	buffer_put_int(m, forced_command != NULL);

	mm_append_debug(m);

	mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m);

	if (type == MM_RSAHOSTKEY)
		monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);

	return (0);
}

Project: openssh-portable

mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
{
	Buffer m;
	u_char *blob;
	u_int len;
	int verified = 0;

	debug3("%s entering", __func__);

	/* Convert the key to a blob and the pass it over */
	if (!key_to_blob(key, &blob, &len))
		return (0);

	buffer_init(&m);
	buffer_put_string(&m, blob, len);
	buffer_put_string(&m, sig, siglen);
	buffer_put_string(&m, data, datalen);
	xfree(blob);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);

	debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);

	verified = buffer_get_int(&m);

	buffer_free(&m);

	return (verified);
}

Project: openssh-portable

mm_answer_pam_query(int socket, Buffer *m)
{
	char *name, *info, **prompts;
	u_int num, *echo_on;
	int i, ret;

	debug3("%s", __func__);
	sshpam_authok = NULL;
	ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on);
	if (ret == 0 && num == 0)
		sshpam_authok = sshpam_ctxt;
	if (num > 1 || name == NULL || info == NULL)
		ret = -1;
	buffer_clear(m);
	buffer_put_int(m, ret);
	buffer_put_cstring(m, name);
	xfree(name);
	buffer_put_cstring(m, info);
	xfree(info);
	buffer_put_int(m, num);
	for (i = 0; i < num; ++i) {
		buffer_put_cstring(m, prompts[i]);
		xfree(prompts[i]);
		buffer_put_int(m, echo_on[i]);
	}
	if (prompts != NULL)
		xfree(prompts);
	if (echo_on != NULL)
		xfree(echo_on);
	mm_request_send(socket, MONITOR_ANS_PAM_QUERY, m);
	return (0);
}

Project: openssh-portable

pthread_create(sp_pthread_t *thread, const void *attr __unused,
    void *(*thread_start)(void *), void *arg)
{
	pid_t pid;

	switch ((pid = fork())) {
	case -1:
		error("fork(): %s", strerror(errno));
		return (-1);
	case 0:
		thread_start(arg);
		_exit(1);
	default:
		*thread = pid;
		return (0);
	}
}

Project: openssh-portable

mm_session_close(Session *s)
{
	debug3("%s: session %d pid %d", __func__, s->self, s->pid);
	if (s->ttyfd != -1) {
		debug3("%s: tty %s ptyfd %d",  __func__, s->tty, s->ptyfd);
		fatal_remove_cleanup(session_pty_cleanup2, (void *)s);
		session_pty_cleanup2(s);
	}
	s->used = 0;
}

Project: openssh-portable

pthread_exit(void *value __unused)
{
	_exit(0);
}

Project: openssh-portable

privsep_challenge_enable(void)
{
#ifdef BSD_AUTH
	extern KbdintDevice mm_bsdauth_device;
#endif
#ifdef USE_PAM
	extern KbdintDevice mm_sshpam_device;
#endif
#ifdef SKEY
	extern KbdintDevice mm_skey_device;
#endif
	int n = 0;

#ifdef BSD_AUTH
	devices[n++] = &mm_bsdauth_device;
#else
#ifdef USE_PAM
	devices[n++] = &mm_sshpam_device;
#endif
#ifdef SKEY
	devices[n++] = &mm_skey_device;
#endif
#endif
}

Project: openssh-portable

do_authentication(void)
{
	Authctxt *authctxt;
	u_int ulen;
	char *user, *style = NULL;

	/* Get the name of the user that we wish to log in as. */
	packet_read_expect(SSH_CMSG_USER);

	/* Get the user name. */
	user = packet_get_string(&ulen);
	packet_check_eom();

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

#ifdef KRB5
	/* XXX - SSH.com Kerberos v5 braindeath. */
	if ((datafellows & SSH_BUG_K5USER) &&
	    options.kerberos_authentication) {
		char *p;
		if ((p = strchr(user, '@')) != NULL)
			*p = '\0';
	}
#endif

	authctxt = authctxt_new();
	authctxt->user = user;
	authctxt->style = style;

	/* Verify that the user is a valid user. */
	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
		authctxt->valid = 1;
	else
		debug("do_authentication: illegal user %s", user);

	setproctitle("%s%s", authctxt->pw ? user : "unknown",
	    use_privsep ? " [net]" : "");

#ifdef USE_PAM
	PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user));
#endif

	/*
	 * If we are not running as root, the user must have the same uid as
	 * the server. (Unless you are running Windows)
	 */
#ifndef HAVE_CYGWIN
	if (!use_privsep && getuid() != 0 && authctxt->pw &&
	    authctxt->pw->pw_uid != getuid())
		packet_disconnect("Cannot change user when server not running as root.");
#endif

	/*
	 * Loop until the user has been authenticated or the connection is
	 * closed, do_authloop() returns only if authentication is successful
	 */
	do_authloop(authctxt);

	/* The user has been authenticated and accepted. */
	packet_start(SSH_SMSG_SUCCESS);
	packet_send();
	packet_write_wait();

	return (authctxt);
}

Project: openssh-portable
File: monitor_wrap.c

mm_terminate(void)
{
	Buffer m;

	buffer_init(&m);
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
	buffer_free(&m);
}

Project: openssh-portable

start_pam(const char *user)
{
	if (sshpam_init(user) == -1)
		fatal("PAM: initialisation failed");
}

Project: openssh-portable

mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
	Buffer m;
	Key *key;
	u_char *blob;
	u_int blen;
	int allowed = 0, have_forced = 0;

	debug3("%s entering", __func__);

	buffer_init(&m);
	buffer_put_bignum2(&m, client_n);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);

	allowed = buffer_get_int(&m);

	/* fake forced command */
	auth_clear_options();
	have_forced = buffer_get_int(&m);
	forced_command = have_forced ? xstrdup("true") : NULL;

	if (allowed && rkey != NULL) {
		blob = buffer_get_string(&m, &blen);
		if ((key = key_from_blob(blob, blen)) == NULL)
			fatal("%s: key_from_blob failed", __func__);
		*rkey = key;
		xfree(blob);
	}
	mm_send_debug(&m);
	buffer_free(&m);

	return (allowed);
}

Project: openssh-portable

mm_init_compression(struct mm_master *mm)
{
	outgoing_stream.zalloc = (alloc_func)mm_zalloc;
	outgoing_stream.zfree = (free_func)mm_zfree;
	outgoing_stream.opaque = mm;

	incoming_stream.zalloc = (alloc_func)mm_zalloc;
	incoming_stream.zfree = (free_func)mm_zfree;
	incoming_stream.opaque = mm;
}

Project: openssh-portable

mm_answer_rsa_response(int socket, Buffer *m)
{
	Key *key = NULL;
	u_char *blob, *response;
	u_int blen, len;
	int success;

	debug3("%s entering", __func__);

	if (!authctxt->valid)
		fatal("%s: authctxt not valid", __func__);
	if (ssh1_challenge == NULL)
		fatal("%s: no ssh1_challenge", __func__);

	blob = buffer_get_string(m, &blen);
	if (!monitor_allowed_key(blob, blen))
		fatal("%s: bad key, not previously allowed", __func__);
	if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
		fatal("%s: key type mismatch: %d", __func__, key_blobtype);
	if ((key = key_from_blob(blob, blen)) == NULL)
		fatal("%s: received bad key", __func__);
	response = buffer_get_string(m, &len);
	if (len != 16)
		fatal("%s: received bad response to challenge", __func__);
	success = auth_rsa_verify_response(key, ssh1_challenge, response);

	xfree(blob);
	key_free(key);
	xfree(response);

	auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";

	/* reset state */
	BN_clear_free(ssh1_challenge);
	ssh1_challenge = NULL;
	monitor_reset_key_state();

	buffer_clear(m);
	buffer_put_int(m, success);
	mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m);

	return (success);
}

Project: openssh-portable

monitor_child_preauth(struct monitor *pmonitor)
{
	struct mon_table *ent;
	int authenticated = 0;

	debug3("preauth child monitor started");

	if (compat20) {
		mon_dispatch = mon_dispatch_proto20;

		/* Permit requests for moduli and signatures */
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
	} else {
		mon_dispatch = mon_dispatch_proto15;

		monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
	}

	authctxt = authctxt_new();

	/* The first few requests do not require asynchronous access */
	while (!authenticated) {
		authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
		if (authenticated) {
			if (!(ent->flags & MON_AUTHDECIDE))
				fatal("%s: unexpected authentication from %d",
				    __func__, ent->type);
			if (authctxt->pw->pw_uid == 0 &&
			    !auth_root_allowed(auth_method))
				authenticated = 0;
		}

		if (ent->flags & MON_AUTHDECIDE) {
			auth_log(authctxt, authenticated, auth_method,
			    compat20 ? " ssh2" : "");
			if (!authenticated)
				authctxt->failures++;
		}
	}

	if (!authctxt->valid)
		fatal("%s: authenticated invalid user", __func__);

	debug("%s: %s has been authenticated by privileged process",
	    __func__, authctxt->user);

	mm_get_keystate(pmonitor);

	return (authctxt);
}

Project: openssh-portable

mm_answer_pam_respond(int socket, Buffer *m)
{
	char **resp;
	u_int num;
	int i, ret;

	debug3("%s", __func__);
	sshpam_authok = NULL;
	num = buffer_get_int(m);
	if (num > 0) {
		resp = xmalloc(num * sizeof(char *));
		for (i = 0; i < num; ++i)
			resp[i] = buffer_get_string(m, NULL);
		ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
		for (i = 0; i < num; ++i)
			xfree(resp[i]);
		xfree(resp);
	} else {
		ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL);
	}
	buffer_clear(m);
	buffer_put_int(m, ret);
	mm_request_send(socket, MONITOR_ANS_PAM_RESPOND, m);
	auth_method = "keyboard-interactive/pam";
	if (ret == 0)
		sshpam_authok = sshpam_ctxt;
	return (0);
}

Project: openssh-portable

monitor_read(struct monitor *pmonitor, struct mon_table *ent,
    struct mon_table **pent)
{
	Buffer m;
	int ret;
	u_char type;

	buffer_init(&m);

	mm_request_receive(pmonitor->m_sendfd, &m);
	type = buffer_get_char(&m);

	debug3("%s: checking request %d", __func__, type);

	while (ent->f != NULL) {
		if (ent->type == type)
			break;
		ent++;
	}

	if (ent->f != NULL) {
		if (!(ent->flags & MON_PERMIT))
			fatal("%s: unpermitted request %d", __func__,
			    type);
		ret = (*ent->f)(pmonitor->m_sendfd, &m);
		buffer_free(&m);

		/* The child may use this request only once, disable it */
		if (ent->flags & MON_ONCE) {
			debug2("%s: %d used once, disabling now", __func__,
			    type);
			ent->flags &= ~MON_PERMIT;
		}

		if (pent != NULL)
			*pent = ent;

		return ret;
	}

	fatal("%s: unsupported request: %d", __func__, type);

	/* NOTREACHED */
	return (-1);
}

Project: openssh-portable

mm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
{
	u_int mlen = buffer_len(m);
	u_char buf[5];

	debug3("%s entering: type %d", __func__, type);

	PUT_32BIT(buf, mlen + 1);
	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
	if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf))
		fatal("%s: write", __func__);
	if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen)
		fatal("%s: write", __func__);
}

Project: openssh-portable

mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
    Key *key)
{
	return (mm_key_allowed(MM_HOSTKEY, user, host, key));
}

Project: openssh-portable

mm_answer_pwnamallow(int socket, Buffer *m)
{
	char *login;
	struct passwd *pwent;
	int allowed = 0;

	debug3("%s", __func__);

	if (authctxt->attempt++ != 0)
		fatal("%s: multiple attempts for getpwnam", __func__);

	login = buffer_get_string(m, NULL);

	pwent = getpwnamallow(login);

	authctxt->user = xstrdup(login);
	setproctitle("%s [priv]", pwent ? login : "unknown");
	xfree(login);

	buffer_clear(m);

	if (pwent == NULL) {
		buffer_put_char(m, 0);
		goto out;
	}

	allowed = 1;
	authctxt->pw = pwent;
	authctxt->valid = 1;

	buffer_put_char(m, 1);
	buffer_put_string(m, pwent, sizeof(struct passwd));
	buffer_put_cstring(m, pwent->pw_name);
	buffer_put_cstring(m, "*");
	buffer_put_cstring(m, pwent->pw_gecos);
#ifdef HAVE_PW_CLASS_IN_PASSWD
	buffer_put_cstring(m, pwent->pw_class);
#endif
	buffer_put_cstring(m, pwent->pw_dir);
	buffer_put_cstring(m, pwent->pw_shell);

 out:
	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
	mm_request_send(socket, MONITOR_ANS_PWNAM, m);

	/* For SSHv1 allow authentication now */
	if (!compat20)
		monitor_permit_authentications(1);
	else {
		/* Allow service/style information on the auth context */
		monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
	}

#ifdef USE_PAM
	monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
#endif

	return (0);
}

Project: openssh-portable

mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
{
	u_char rtype;

	debug3("%s entering: type %d", __func__, type);

	mm_request_receive(socket, m);
	rtype = buffer_get_char(m);
	if (rtype != type)
		fatal("%s: read: rtype %d != type %d", __func__,
		    rtype, type);
}

Project: openssh-portable

auth_password(Authctxt *authctxt, const char *password)
{
	struct passwd * pw = authctxt->pw;
	int ok = authctxt->valid;
#if !defined(HAVE_OSF_SIA)
	char *encrypted_password;
	char *pw_password;
	char *salt;
# if defined(__hpux) || defined(HAVE_SECUREWARE)
	struct pr_passwd *spw;
# endif /* __hpux || HAVE_SECUREWARE */
# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
	struct spwd *spw;
# endif
# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
	struct passwd_adjunct *spw;
# endif
# ifdef WITH_AIXAUTHENTICATE
	char *authmsg;
	int authsuccess;
	int reenter = 1;
# endif
#endif /* !defined(HAVE_OSF_SIA) */

	/* deny if no user. */
	if (pw == NULL)
		ok = 0;
#ifndef HAVE_CYGWIN
	if (pw && pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
		ok = 0;
#endif
	if (*password == '\0' && options.permit_empty_passwd == 0)
		ok = 0;

#if defined(HAVE_OSF_SIA)
	if (!ok)
		return 0;
	return auth_sia_password(authctxt, password);
#else
	if (!ok)
		return 0;
# ifdef KRB5
	if (options.kerberos_authentication == 1) {
		int ret = auth_krb5_password(authctxt, password);
		if (ret == 1 || ret == 0)
			return ret;
		/* Fall back to ordinary passwd authentication. */
	}
# endif
# ifdef HAVE_CYGWIN
	if (is_winnt) {
		HANDLE hToken = cygwin_logon_user(pw, password);

		if (hToken == INVALID_HANDLE_VALUE)
			return 0;
		cygwin_set_impersonation_token(hToken);
		return 1;
	}
# endif
# ifdef WITH_AIXAUTHENTICATE
	authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);

	if (authsuccess)
	        /* We don't have a pty yet, so just label the line as "ssh" */
	        if (loginsuccess(authctxt->user,
			get_canonical_hostname(options.verify_reverse_mapping),
			"ssh", &aixloginmsg) < 0)
				aixloginmsg = NULL;

	return(authsuccess);
# endif
# ifdef KRB4
	if (options.kerberos_authentication == 1) {
		int ret = auth_krb4_password(authctxt, password);
		if (ret == 1 || ret == 0)
			return ret;
		/* Fall back to ordinary passwd authentication. */
	}
# endif
# ifdef BSD_AUTH
	if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh",
	    (char *)password) == 0)
		return 0;
	else
		return 1;
# endif
	pw_password = pw->pw_passwd;

	/*
	 * Various interfaces to shadow or protected password data
	 */
# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
	spw = getspnam(pw->pw_name);
	if (spw != NULL)
		pw_password = spw->sp_pwdp;
# endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */

# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
	if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL)
		pw_password = spw->pwa_passwd;
# endif /* defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) */

# ifdef HAVE_SECUREWARE
	if ((spw = getprpwnam(pw->pw_name)) != NULL)
		pw_password = spw->ufld.fd_encrypt;
# endif /* HAVE_SECUREWARE */

# if defined(__hpux) && !defined(HAVE_SECUREWARE)
	if (iscomsec() && (spw = getprpwnam(pw->pw_name)) != NULL)
		pw_password = spw->ufld.fd_encrypt;
# endif /* defined(__hpux) && !defined(HAVE_SECUREWARE) */

	/* Check for users with no password. */
	if ((password[0] == '\0') && (pw_password[0] == '\0'))
		return 1;

	if (pw_password[0] != '\0')
		salt = pw_password;
	else
		salt = "xx";

# ifdef HAVE_MD5_PASSWORDS
	if (is_md5_salt(salt))
		encrypted_password = md5_crypt(password, salt);
	else
		encrypted_password = crypt(password, salt);
# else /* HAVE_MD5_PASSWORDS */
#  if defined(__hpux) && !defined(HAVE_SECUREWARE)
	if (iscomsec())
		encrypted_password = bigcrypt(password, salt);
	else
		encrypted_password = crypt(password, salt);
#  else
#   ifdef HAVE_SECUREWARE
	encrypted_password = bigcrypt(password, salt);
#   else
	encrypted_password = crypt(password, salt);
#   endif /* HAVE_SECUREWARE */
#  endif /* __hpux && !defined(HAVE_SECUREWARE) */
# endif /* HAVE_MD5_PASSWORDS */

	/* Authentication is accepted if the encrypted passwords are identical. */
	return (strcmp(encrypted_password, pw_password) == 0);
#endif /* !HAVE_OSF_SIA */
}

Project: openssh-portable

mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
    char *host, Key *key)
{
	int ret;

	key->type = KEY_RSA; /* XXX hack for key_to_blob */
	ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
	key->type = KEY_RSA1;
	return (ret);
}

Project: openssh-portable

sshpam_cleanup(void *arg)
{
	(void)arg;
	debug("PAM: cleanup");
	pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
	if (sshpam_cred_established) {
		pam_setcred(sshpam_handle, PAM_DELETE_CRED);
		sshpam_cred_established = 0;
	}
	if (sshpam_session_open) {
		pam_close_session(sshpam_handle, PAM_SILENT);
		sshpam_session_open = 0;
	}
	sshpam_authenticated = sshpam_new_authtok_reqd = 0;
	pam_end(sshpam_handle, sshpam_err);
	sshpam_handle = NULL;
}

Project: openssh-portable

mm_answer_rsa_challenge(int socket, Buffer *m)
{
	Key *key = NULL;
	u_char *blob;
	u_int blen;

	debug3("%s entering", __func__);

	if (!authctxt->valid)
		fatal("%s: authctxt not valid", __func__);
	blob = buffer_get_string(m, &blen);
	if (!monitor_allowed_key(blob, blen))
		fatal("%s: bad key, not previously allowed", __func__);
	if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
		fatal("%s: key type mismatch", __func__);
	if ((key = key_from_blob(blob, blen)) == NULL)
		fatal("%s: received bad key", __func__);

	if (ssh1_challenge)
		BN_clear_free(ssh1_challenge);
	ssh1_challenge = auth_rsa_generate_challenge(key);

	buffer_clear(m);
	buffer_put_bignum2(m, ssh1_challenge);

	debug3("%s sending reply", __func__);
	mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m);

	monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);

	xfree(blob);
	key_free(key);
	return (0);
}

Project: openssh-portable

mm_answer_bsdauthquery(int socket, Buffer *m)
{
	char *name, *infotxt;
	u_int numprompts;
	u_int *echo_on;
	char **prompts;
	u_int success;

	success = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
	    &prompts, &echo_on) < 0 ? 0 : 1;

	buffer_clear(m);
	buffer_put_int(m, success);
	if (success)
		buffer_put_cstring(m, prompts[0]);

	debug3("%s: sending challenge success: %u", __func__, success);
	mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m);

	if (success) {
		xfree(name);
		xfree(infotxt);
		xfree(prompts);
		xfree(echo_on);
	}

	return (0);
}

Project: openssh-portable

mm_answer_term(int socket, Buffer *req)
{
	extern struct monitor *pmonitor;
	int res, status;

	debug3("%s: tearing down sessions", __func__);

	/* The child is terminating */
	session_destroy_all(&mm_session_close);

	while (waitpid(pmonitor->m_pid, &status, 0) == -1)
		if (errno != EINTR)
			exit(1);

	res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;

	/* Terminate process */
	exit (res);
}

Project: openssh-portable

mm_answer_sign(int socket, Buffer *m)
{
	Key *key;
	u_char *p;
	u_char *signature;
	u_int siglen, datlen;
	int keyid;

	debug3("%s", __func__);

	keyid = buffer_get_int(m);
	p = buffer_get_string(m, &datlen);

	if (datlen != 20)
		fatal("%s: data length incorrect: %u", __func__, datlen);

	/* save session id, it will be passed on the first call */
	if (session_id2_len == 0) {
		session_id2_len = datlen;
		session_id2 = xmalloc(session_id2_len);
		memcpy(session_id2, p, session_id2_len);
	}

	if ((key = get_hostkey_by_index(keyid)) == NULL)
		fatal("%s: no hostkey from index %d", __func__, keyid);
	if (key_sign(key, &signature, &siglen, p, datlen) < 0)
		fatal("%s: key_sign failed", __func__);

	debug3("%s: signature %p(%u)", __func__, signature, siglen);

	buffer_clear(m);
	buffer_put_string(m, signature, siglen);

	xfree(p);
	xfree(signature);

	mm_request_send(socket, MONITOR_ANS_SIGN, m);

	/* Turn on permissions for getpwnam */
	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);

	return (0);
}

Project: openssh-portable

mm_answer_pty(int socket, Buffer *m)
{
	extern struct monitor *pmonitor;
	Session *s;
	int res, fd0;

	debug3("%s entering", __func__);

	buffer_clear(m);
	s = session_new();
	if (s == NULL)
		goto error;
	s->authctxt = authctxt;
	s->pw = authctxt->pw;
	s->pid = pmonitor->m_pid;
	res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
	if (res == 0)
		goto error;
	fatal_add_cleanup(session_pty_cleanup2, (void *)s);
	pty_setowner(authctxt->pw, s->tty);

	buffer_put_int(m, 1);
	buffer_put_cstring(m, s->tty);
	mm_request_send(socket, MONITOR_ANS_PTY, m);

	mm_send_fd(socket, s->ptyfd);
	mm_send_fd(socket, s->ttyfd);

	/* We need to trick ttyslot */
	if (dup2(s->ttyfd, 0) == -1)
		fatal("%s: dup2", __func__);

	mm_record_login(s, authctxt->pw);

	/* Now we can close the file descriptor again */
	close(0);

	/* make sure nothing uses fd 0 */
	if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
		fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
	if (fd0 != 0)
		error("%s: fd0 %d != 0", __func__, fd0);

	/* slave is not needed */
	close(s->ttyfd);
	s->ttyfd = s->ptyfd;
	/* no need to dup() because nobody closes ptyfd */
	s->ptymaster = s->ptyfd;

	debug3("%s: tty %s ptyfd %d",  __func__, s->tty, s->ttyfd);

	return (0);

 error:
	if (s != NULL)
		mm_session_close(s);
	buffer_put_int(m, 0);
	mm_request_send(socket, MONITOR_ANS_PTY, m);
	return (0);
}

Project: openssh-portable

monitor_child_postauth(struct monitor *pmonitor)
{
	if (compat20) {
		mon_dispatch = mon_dispatch_postauth20;

		/* Permit requests for moduli and signatures */
		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);

	} else {
		mon_dispatch = mon_dispatch_postauth15;
		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
	}
	if (!no_pty_flag) {
		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
		monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
	}

	for (;;)
		monitor_read(pmonitor, mon_dispatch, NULL);
}

Project: openssh-portable

monitor_socketpair(int *pair)
{
#ifdef HAVE_SOCKETPAIR
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
		fatal("%s: socketpair", __func__);
#else
	fatal("%s: UsePrivilegeSeparation=yes not supported",
	    __func__);
#endif
	FD_CLOSEONEXEC(pair[0]);
	FD_CLOSEONEXEC(pair[1]);
}

Project: openssh-portable

sshpam_thread(void *ctxtp)
{
	struct pam_ctxt *ctxt = ctxtp;
	Buffer buffer;
	struct pam_conv sshpam_conv = { sshpam_thread_conv, ctxt };
#ifndef USE_POSIX_THREADS
	const char *pam_user;

	pam_get_item(sshpam_handle, PAM_USER, (const void **)&pam_user);
	setproctitle("%s [pam]", pam_user);
#endif

	buffer_init(&buffer);
	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
	    (const void *)&sshpam_conv);
	if (sshpam_err != PAM_SUCCESS)
		goto auth_fail;
	sshpam_err = pam_authenticate(sshpam_handle, 0);
	if (sshpam_err != PAM_SUCCESS)
		goto auth_fail;
	sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
	if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD)
		goto auth_fail;
	buffer_put_cstring(&buffer, "OK");
	ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer);
	buffer_free(&buffer);
	pthread_exit(NULL);

 auth_fail:
	buffer_put_cstring(&buffer,
	    pam_strerror(sshpam_handle, sshpam_err));
	ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
	buffer_free(&buffer);
	pthread_exit(NULL);
	
	return (NULL); /* Avoid warning for non-pthread case */
}

Project: openssh-portable

pam_chauthtok_conv(int n,
	 const struct pam_message **msg,
	 struct pam_response **resp,
	 void *data)
{
	char input[PAM_MAX_MSG_SIZE];
	int i;

	if (n <= 0 || n > PAM_MAX_NUM_MSG)
		return (PAM_CONV_ERR);
	*resp = xmalloc(n * sizeof **resp);
	for (i = 0; i < n; ++i) {
		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
		case PAM_PROMPT_ECHO_OFF:
			resp[i]->resp =
			    read_passphrase(PAM_MSG_MEMBER(msg, i, msg), 
			    RP_ALLOW_STDIN);
			resp[i]->resp_retcode = PAM_SUCCESS;
			break;
		case PAM_PROMPT_ECHO_ON:
			fputs(PAM_MSG_MEMBER(msg, i, msg), stderr);
			fgets(input, sizeof input, stdin);
			resp[i]->resp = xstrdup(input);
			resp[i]->resp_retcode = PAM_SUCCESS;
			break;
		case PAM_ERROR_MSG:
		case PAM_TEXT_INFO:
			fputs(PAM_MSG_MEMBER(msg, i, msg), stderr);
			resp[i]->resp_retcode = PAM_SUCCESS;
			break;
		default:
			goto fail;
		}
	}
	return (PAM_SUCCESS);
 fail:
	while (i)
		xfree(resp[--i]);
	xfree(*resp);
	*resp = NULL;
	return (PAM_CONV_ERR);
}

Project: openssh-portable

is_pam_password_change_required(void)
{
	return (sshpam_new_authtok_reqd);
}

Project: openssh-portable

pthread_cancel(sp_pthread_t thread)
{
	return (kill(thread, SIGTERM));
}

Project: openssh-portable

auth2_challenge_stop(Authctxt *authctxt)
{
	/* unregister callback */
	dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
	if (authctxt->kbdintctxt != NULL)  {
		kbdint_free(authctxt->kbdintctxt);
		authctxt->kbdintctxt = NULL;
	}
}

Project: openssh-portable

mm_session_pty_cleanup2(void *session)
{
	Session *s = session;
	Buffer m;

	if (s->ttyfd == -1)
		return;
	buffer_init(&m);
	buffer_put_cstring(&m, s->tty);
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
	buffer_free(&m);

	/* closed dup'ed master */
	if (close(s->ptymaster) < 0)
		error("close(s->ptymaster): %s", strerror(errno));

	/* unlink pty from session */
	s->ttyfd = -1;
}

Project: openssh-portable

kbdint_free(KbdintAuthctxt *kbdintctxt)
{
	if (kbdintctxt->device)
		kbdint_reset_device(kbdintctxt);
	if (kbdintctxt->devices) {
		xfree(kbdintctxt->devices);
		kbdintctxt->devices = NULL;
	}
	xfree(kbdintctxt);
}

Project: openssh-portable

mm_answer_krb5(int socket, Buffer *m)
{
	krb5_data tkt, reply;
	char *client_user;
	u_int len;
	int success;

	/* use temporary var to avoid size issues on 64bit arch */
	tkt.data = buffer_get_string(m, &len);
	tkt.length = len;

	success = options.kerberos_authentication &&
	    authctxt->valid &&
	    auth_krb5(authctxt, &tkt, &client_user, &reply);

	if (tkt.length)
		xfree(tkt.data);

	buffer_clear(m);
	buffer_put_int(m, success);

	if (success) {
		buffer_put_cstring(m, client_user);
		buffer_put_string(m, reply.data, reply.length);
		if (client_user)
			xfree(client_user);
		if (reply.length)
			xfree(reply.data);
	}
	mm_request_send(socket, MONITOR_ANS_KRB5, m);

	return success;
}

Project: openssh-portable

mm_answer_rsa_keyallowed(int socket, Buffer *m)
{
	BIGNUM *client_n;
	Key *key = NULL;
	u_char *blob = NULL;
	u_int blen = 0;
	int allowed = 0;

	debug3("%s entering", __func__);

	if (options.rsa_authentication && authctxt->valid) {
		if ((client_n = BN_new()) == NULL)
			fatal("%s: BN_new", __func__);
		buffer_get_bignum2(m, client_n);
		allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
		BN_clear_free(client_n);
	}
	buffer_clear(m);
	buffer_put_int(m, allowed);
	buffer_put_int(m, forced_command != NULL);

	/* clear temporarily storage (used by generate challenge) */
	monitor_reset_key_state();

	if (allowed && key != NULL) {
		key->type = KEY_RSA;	/* cheat for key_to_blob */
		if (key_to_blob(key, &blob, &blen) == 0)
			fatal("%s: key_to_blob failed", __func__);
		buffer_put_string(m, blob, blen);

		/* Save temporarily for comparison in verify */
		key_blob = blob;
		key_bloblen = blen;
		key_blobtype = MM_RSAUSERKEY;
	}
	if (key != NULL)
		key_free(key);

	mm_append_debug(m);

	mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m);

	monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
	monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
	return (0);
}

Project: openssh-portable

mm_auth_krb4(Authctxt *authctxt, void *_auth, char **client, void *_reply)
{
	KTEXT auth, reply;
 	Buffer m;
	u_int rlen;
	int success = 0;
	char *p;

	debug3("%s entering", __func__);
	auth = _auth;
	reply = _reply;

	buffer_init(&m);
	buffer_put_string(&m, auth->dat, auth->length);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB4, &m);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB4, &m);

	success = buffer_get_int(&m);
	if (success) {
		*client = buffer_get_string(&m, NULL);
		p = buffer_get_string(&m, &rlen);
		if (rlen >= MAX_KTXT_LEN)
			fatal("%s: reply from monitor too large", __func__);
		reply->length = rlen;
		memcpy(reply->dat, p, rlen);
		memset(p, 0, rlen);
		xfree(p);
	}
	buffer_free(&m);
	return (success);
}

Project: openssh-portable

mm_answer_sessid(int socket, Buffer *m)
{
	int i;

	debug3("%s entering", __func__);

	if (buffer_len(m) != 16)
		fatal("%s: bad ssh1 session id", __func__);
	for (i = 0; i < 16; i++)
		session_id[i] = buffer_get_char(m);

	/* Turn on permissions for getpwnam */
	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);

	return (0);
}

Project: openssh-portable

send_userauth_info_request(Authctxt *authctxt)
{
	KbdintAuthctxt *kbdintctxt;
	char *name, *instr, **prompts;
	int i;
	u_int *echo_on;

	kbdintctxt = authctxt->kbdintctxt;
	if (kbdintctxt->device->query(kbdintctxt->ctxt,
	    &name, &instr, &kbdintctxt->nreq, &prompts, &echo_on))
		return 0;

	packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
	packet_put_cstring(name);
	packet_put_cstring(instr);
	packet_put_cstring("");		/* language not used */
	packet_put_int(kbdintctxt->nreq);
	for (i = 0; i < kbdintctxt->nreq; i++) {
		packet_put_cstring(prompts[i]);
		packet_put_char(echo_on[i]);
	}
	packet_send();
	packet_write_wait();

	for (i = 0; i < kbdintctxt->nreq; i++)
		xfree(prompts[i]);
	xfree(prompts);
	xfree(echo_on);
	xfree(name);
	xfree(instr);
	return 1;
}

Project: openssh-portable

mm_get_keystate(struct monitor *pmonitor)
{
	Buffer m;
	u_char *blob, *p;
	u_int bloblen, plen;
	u_int32_t seqnr, packets;
	u_int64_t blocks;

	debug3("%s: Waiting for new keys", __func__);

	buffer_init(&m);
	mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
	if (!compat20) {
		child_state.ssh1protoflags = buffer_get_int(&m);
		child_state.ssh1cipher = buffer_get_int(&m);
		child_state.ssh1key = buffer_get_string(&m,
		    &child_state.ssh1keylen);
		child_state.ivout = buffer_get_string(&m,
		    &child_state.ivoutlen);
		child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
		goto skip;
	} else {
		/* Get the Kex for rekeying */
		*pmonitor->m_pkex = mm_get_kex(&m);
	}

	blob = buffer_get_string(&m, &bloblen);
	current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
	xfree(blob);

	debug3("%s: Waiting for second key", __func__);
	blob = buffer_get_string(&m, &bloblen);
	current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
	xfree(blob);

	/* Now get sequence numbers for the packets */
	seqnr = buffer_get_int(&m);
	blocks = buffer_get_int64(&m);
	packets = buffer_get_int(&m);
	packet_set_state(MODE_OUT, seqnr, blocks, packets);
	seqnr = buffer_get_int(&m);
	blocks = buffer_get_int64(&m);
	packets = buffer_get_int(&m);
	packet_set_state(MODE_IN, seqnr, blocks, packets);

 skip:
	/* Get the key context */
	child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
	child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);

	debug3("%s: Getting compression state", __func__);
	/* Get compression state */
	p = buffer_get_string(&m, &plen);
	if (plen != sizeof(child_state.outgoing))
		fatal("%s: bad request size", __func__);
	memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
	xfree(p);

	p = buffer_get_string(&m, &plen);
	if (plen != sizeof(child_state.incoming))
		fatal("%s: bad request size", __func__);
	memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
	xfree(p);

	/* Network I/O buffers */
	debug3("%s: Getting Network I/O buffers", __func__);
	child_state.input = buffer_get_string(&m, &child_state.ilen);
	child_state.output = buffer_get_string(&m, &child_state.olen);

	buffer_free(&m);
}

Project: openssh-portable

free_pam_environment(char **env)
{
	char **envp;

	for (envp = env; *envp; envp++)
		xfree(*envp);
	xfree(env);
}

Project: openssh-portable

mm_answer_pam_free_ctx(int socket, Buffer *m)
{

	debug3("%s", __func__);
	(sshpam_device.free_ctx)(sshpam_ctxt);
	buffer_clear(m);
	mm_request_send(socket, MONITOR_ANS_PAM_FREE_CTX, m);
	return (sshpam_authok == sshpam_ctxt);
}

Project: openssh-portable

abandon_challenge_response(Authctxt *authctxt)
{
	if (authctxt->kbdintctxt != NULL) {
		device->free_ctx(authctxt->kbdintctxt);
		authctxt->kbdintctxt = NULL;
	}
}

Project: openssh-portable

mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
    char ***prompts, u_int **echo_on)
{
	*name = xstrdup("");
	*infotxt = xstrdup("");
	*numprompts = 1;
	*prompts = xmalloc(*numprompts * sizeof(char *));
	*echo_on = xmalloc(*numprompts * sizeof(u_int));
	(*echo_on)[0] = 0;
}

Project: openssh-portable

sshpam_thread_conv(int n,
	 const struct pam_message **msg,
	 struct pam_response **resp,
	 void *data)
{
	Buffer buffer;
	struct pam_ctxt *ctxt;
	int i;

	ctxt = data;
	if (n <= 0 || n > PAM_MAX_NUM_MSG)
		return (PAM_CONV_ERR);
	*resp = xmalloc(n * sizeof **resp);
	buffer_init(&buffer);
	for (i = 0; i < n; ++i) {
		resp[i]->resp_retcode = 0;
		resp[i]->resp = NULL;
		switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
		case PAM_PROMPT_ECHO_OFF:
			buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg));
			ssh_msg_send(ctxt->pam_csock, 
			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer);
			ssh_msg_recv(ctxt->pam_csock, &buffer);
			if (buffer_get_char(&buffer) != PAM_AUTHTOK)
				goto fail;
			resp[i]->resp = buffer_get_string(&buffer, NULL);
			break;
		case PAM_PROMPT_ECHO_ON:
			buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg));
			ssh_msg_send(ctxt->pam_csock, 
			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer);
			ssh_msg_recv(ctxt->pam_csock, &buffer);
			if (buffer_get_char(&buffer) != PAM_AUTHTOK)
				goto fail;
			resp[i]->resp = buffer_get_string(&buffer, NULL);
			break;
		case PAM_ERROR_MSG:
			buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg));
			ssh_msg_send(ctxt->pam_csock, 
			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer);
			break;
		case PAM_TEXT_INFO:
			buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg));
			ssh_msg_send(ctxt->pam_csock, 
			    PAM_MSG_MEMBER(msg, i, msg_style), &buffer);
			break;
		default:
			goto fail;
		}
		buffer_clear(&buffer);
	}
	buffer_free(&buffer);
	return (PAM_SUCCESS);
 fail:
	while (i)
		xfree(resp[--i]);
	xfree(*resp);
	*resp = NULL;
	buffer_free(&buffer);
	return (PAM_CONV_ERR);
}

Project: openssh-portable

do_pam_setcred(int init)
{
	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
	    (const void *)&null_conv);
	if (sshpam_err != PAM_SUCCESS)
		fatal("PAM: failed to set PAM_CONV: %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	if (init) {
		debug("PAM: establishing credentials");
		sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED);
	} else {
		debug("PAM: reinitializing credentials");
		sshpam_err = pam_setcred(sshpam_handle, PAM_REINITIALIZE_CRED);
	}
	if (sshpam_err == PAM_SUCCESS) {
		sshpam_cred_established = 1;
		return;
	}
	if (sshpam_authenticated)
		fatal("PAM: pam_setcred(): %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	else
		debug("PAM: pam_setcred(): %s",
		    pam_strerror(sshpam_handle, sshpam_err));
}

Project: openssh-portable

mm_skey_query(void *ctx, char **name, char **infotxt,
   u_int *numprompts, char ***prompts, u_int **echo_on)
{
	Buffer m;
	int len;
	u_int success;
	char *p, *challenge;

	debug3("%s: entering", __func__);

	buffer_init(&m);
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);

	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
	    &m);
	success = buffer_get_int(&m);
	if (success == 0) {
		debug3("%s: no challenge", __func__);
		buffer_free(&m);
		return (-1);
	}

	/* Get the challenge, and format the response */
	challenge  = buffer_get_string(&m, NULL);
	buffer_free(&m);

	debug3("%s: received challenge: %s", __func__, challenge);

	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);

	len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
	p = xmalloc(len);
	strlcpy(p, challenge, len);
	strlcat(p, SKEY_PROMPT, len);
	(*prompts)[0] = p;
	xfree(challenge);

	return (0);
}

Project: openssh-portable

mm_send_kex(Buffer *m, Kex *kex)
{
	buffer_put_string(m, kex->session_id, kex->session_id_len);
	buffer_put_int(m, kex->we_need);
	buffer_put_int(m, kex->hostkey_type);
	buffer_put_int(m, kex->kex_type);
	buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
	buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
	buffer_put_int(m, kex->flags);
	buffer_put_cstring(m, kex->client_version_string);
	buffer_put_cstring(m, kex->server_version_string);
}

Project: openssh-portable

get_challenge(Authctxt *authctxt)
{
	char *challenge, *name, *info, **prompts;
	u_int i, numprompts;
	u_int *echo_on;

	device = devices[0]; /* we always use the 1st device for protocol 1 */
	if (device == NULL)
		return NULL;
	if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL)
		return NULL;
	if (device->query(authctxt->kbdintctxt, &name, &info,
	    &numprompts, &prompts, &echo_on)) {
		device->free_ctx(authctxt->kbdintctxt);
		authctxt->kbdintctxt = NULL;
		return NULL;
	}
	if (numprompts < 1)
		fatal("get_challenge: numprompts < 1");
	challenge = xstrdup(prompts[0]);
	for (i = 0; i < numprompts; i++)
		xfree(prompts[i]);
	xfree(prompts);
	xfree(name);
	xfree(echo_on);
	xfree(info);

	return (challenge);
}

Project: openssh-portable

mm_record_login(Session *s, struct passwd *pw)
{
	socklen_t fromlen;
	struct sockaddr_storage from;

	/*
	 * Get IP address of client. If the connection is not a socket, let
	 * the address be 0.0.0.0.
	 */
	memset(&from, 0, sizeof(from));
	fromlen = sizeof(from);
	if (packet_connection_is_on_socket()) {
		if (getpeername(packet_get_connection_in(),
			(struct sockaddr *) & from, &fromlen) < 0) {
			debug("getpeername: %.100s", strerror(errno));
			fatal_cleanup();
		}
	}
	/* Record that there was a login on that tty from the remote host. */
	record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
	    get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
	    (struct sockaddr *)&from, fromlen);
}

Project: openssh-portable

kbdint_next_device(KbdintAuthctxt *kbdintctxt)
{
	size_t len;
	char *t;
	int i;

	if (kbdintctxt->device)
		kbdint_reset_device(kbdintctxt);
	do {
		len = kbdintctxt->devices ?
		    strcspn(kbdintctxt->devices, ",") : 0;

		if (len == 0)
			break;
		for (i = 0; devices[i]; i++)
			if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0)
				kbdintctxt->device = devices[i];
		t = kbdintctxt->devices;
		kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL;
		xfree(t);
		debug2("kbdint_next_device: devices %s", kbdintctxt->devices ?
		   kbdintctxt->devices : "<empty>");
	} while (kbdintctxt->devices && !kbdintctxt->device);

	return kbdintctxt->device ? 1 : 0;
}

Project: openssh-portable

verify_response(Authctxt *authctxt, const char *response)
{
	char *resp[1];
	int res;

	if (device == NULL)
		return 0;
	if (authctxt->kbdintctxt == NULL)
		return 0;
	resp[0] = (char *)response;
	res = device->respond(authctxt->kbdintctxt, 1, resp);
	if (res == 1) {
		/* postponed - send a null query just in case */
		char *name, *info, **prompts;
		u_int i, numprompts, *echo_on;

		res = device->query(authctxt->kbdintctxt, &name, &info,
		    &numprompts, &prompts, &echo_on);
		if (res == 0) {
			for (i = 0; i < numprompts; i++)
				xfree(prompts[i]);
			xfree(prompts);
			xfree(name);
			xfree(echo_on);
			xfree(info);
		}
		/* if we received more prompts, we're screwed */
		res = (numprompts != 0);
	}
	device->free_ctx(authctxt->kbdintctxt);
	authctxt->kbdintctxt = NULL;
	return res ? 0 : 1;
}

Project: openssh-portable

get_authname(int type)
{
	static char buf[1024];
	switch (type) {
	case SSH_CMSG_AUTH_PASSWORD:
		return "password";
	case SSH_CMSG_AUTH_RSA:
		return "rsa";
	case SSH_CMSG_AUTH_RHOSTS_RSA:
		return "rhosts-rsa";
	case SSH_CMSG_AUTH_RHOSTS:
		return "rhosts";
	case SSH_CMSG_AUTH_TIS:
	case SSH_CMSG_AUTH_TIS_RESPONSE:
		return "challenge-response";
#if defined(KRB4) || defined(KRB5)
	case SSH_CMSG_AUTH_KERBEROS:
		return "kerberos";
#endif
	}
	snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
	return buf;
}

Project: openssh-portable

kbdint_alloc(const char *devs)
{
	KbdintAuthctxt *kbdintctxt;
	Buffer b;
	int i;

	kbdintctxt = xmalloc(sizeof(KbdintAuthctxt));
	if (strcmp(devs, "") == 0) {
		buffer_init(&b);
		for (i = 0; devices[i]; i++) {
			if (buffer_len(&b) > 0)
				buffer_append(&b, ",", 1);
			buffer_append(&b, devices[i]->name,
			    strlen(devices[i]->name));
		}
		buffer_append(&b, "\0", 1);
		kbdintctxt->devices = xstrdup(buffer_ptr(&b));
		buffer_free(&b);
	} else {
		kbdintctxt->devices = xstrdup(devs);
	}
	debug("kbdint_alloc: devices '%s'", kbdintctxt->devices);
	kbdintctxt->ctxt = NULL;
	kbdintctxt->device = NULL;
	kbdintctxt->nreq = 0;

	return kbdintctxt;
}

Project: openssh-portable

mm_append_debug(Buffer *m)
{
	if (auth_debug_init && buffer_len(&auth_debug)) {
		debug3("%s: Appending debug messages for child", __func__);
		buffer_append(m, buffer_ptr(&auth_debug),
		    buffer_len(&auth_debug));
		buffer_clear(&auth_debug);
	}
}

Project: openssh-portable

char *mm_auth2_read_banner(void)
{
	Buffer m;
	char *banner;

	debug3("%s entering", __func__);

	buffer_init(&m);
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
	buffer_clear(&m);

	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m);
	banner = buffer_get_string(&m, NULL);
	buffer_free(&m);

	return (banner);
}

Project: openssh-portable

mm_newkeys_from_blob(u_char *blob, int blen)
{
	Buffer b;
	u_int len;
	Newkeys *newkey = NULL;
	Enc *enc;
	Mac *mac;
	Comp *comp;

	debug3("%s: %p(%d)", __func__, blob, blen);
#ifdef DEBUG_PK
	dump_base64(stderr, blob, blen);
#endif
	buffer_init(&b);
	buffer_append(&b, blob, blen);

	newkey = xmalloc(sizeof(*newkey));
	enc = &newkey->enc;
	mac = &newkey->mac;
	comp = &newkey->comp;

	/* Enc structure */
	enc->name = buffer_get_string(&b, NULL);
	buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
	enc->enabled = buffer_get_int(&b);
	enc->block_size = buffer_get_int(&b);
	enc->key = buffer_get_string(&b, &enc->key_len);
	enc->iv = buffer_get_string(&b, &len);
	if (len != enc->block_size)
		fatal("%s: bad ivlen: expected %u != %u", __func__,
		    enc->block_size, len);

	if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
		fatal("%s: bad cipher name %s or pointer %p", __func__,
		    enc->name, enc->cipher);

	/* Mac structure */
	mac->name = buffer_get_string(&b, NULL);
	if (mac->name == NULL || mac_init(mac, mac->name) == -1)
		fatal("%s: can not init mac %s", __func__, mac->name);
	mac->enabled = buffer_get_int(&b);
	mac->key = buffer_get_string(&b, &len);
	if (len > mac->key_len)
		fatal("%s: bad mac key length: %u > %d", __func__, len,
		    mac->key_len);
	mac->key_len = len;

	/* Comp structure */
	comp->type = buffer_get_int(&b);
	comp->enabled = buffer_get_int(&b);
	comp->name = buffer_get_string(&b, NULL);

	len = buffer_len(&b);
	if (len != 0)
		error("newkeys_from_blob: remaining bytes in blob %u", len);
	buffer_free(&b);
	return (newkey);
}

Project: openssh-portable

auth2_challenge_start(Authctxt *authctxt)
{
	KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt;

	debug2("auth2_challenge_start: devices %s",
	    kbdintctxt->devices ?  kbdintctxt->devices : "<empty>");

	if (kbdint_next_device(kbdintctxt) == 0) {
		auth2_challenge_stop(authctxt);
		return 0;
	}
	debug("auth2_challenge_start: trying authentication method '%s'",
	    kbdintctxt->device->name);

	if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) {
		auth2_challenge_stop(authctxt);
		return 0;
	}
	if (send_userauth_info_request(authctxt) == 0) {
		auth2_challenge_stop(authctxt);
		return 0;
	}
	dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE,
	    &input_userauth_info_response);

	authctxt->postponed = 1;
	return 0;
}

Project: openssh-portable

do_authloop(Authctxt *authctxt)
{
	int authenticated = 0;
	u_int bits;
	Key *client_host_key;
	BIGNUM *n;
	char *client_user, *password;
	char info[1024];
	u_int dlen;
	u_int ulen;
	int prev, type = 0;
	struct passwd *pw = authctxt->pw;

	debug("Attempting authentication for %s%.100s.",
	    authctxt->valid ? "" : "illegal user ", authctxt->user);

	/* If the user has no password, accept authentication immediately. */
	if (options.password_authentication &&
#if defined(KRB4) || defined(KRB5)
	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
	    PRIVSEP(auth_password(authctxt, ""))) {
		auth_log(authctxt, 1, "without authentication", "");
		return;
	}

	/* Indicate that authentication is needed. */
	packet_start(SSH_SMSG_FAILURE);
	packet_send();
	packet_write_wait();

	client_user = NULL;

	for (;;) {
		/* default to fail */
		authenticated = 0;

		info[0] = '\0';

		/* Get a packet from the client. */
		prev = type;
		type = packet_read();

		/*
		 * If we started challenge-response authentication but the
		 * next packet is not a response to our challenge, release
		 * the resources allocated by get_challenge() (which would
		 * normally have been released by verify_response() had we
		 * received such a response)
		 */
		if (prev == SSH_CMSG_AUTH_TIS &&
		    type != SSH_CMSG_AUTH_TIS_RESPONSE)
			abandon_challenge_response(authctxt);

		/* Process the packet. */
		switch (type) {

#if defined(KRB4) || defined(KRB5)
		case SSH_CMSG_AUTH_KERBEROS:
			if (!options.kerberos_authentication) {
				verbose("Kerberos authentication disabled.");
			} else {
				char *kdata = packet_get_string(&dlen);
				packet_check_eom();

				if (kdata[0] == 4) { /* KRB_PROT_VERSION */
#ifdef KRB4
					KTEXT_ST tkt, reply;
					tkt.length = dlen;
					if (tkt.length < MAX_KTXT_LEN)
						memcpy(tkt.dat, kdata, tkt.length);

					if (PRIVSEP(auth_krb4(authctxt, &tkt,
					    &client_user, &reply))) {
						authenticated = 1;
						snprintf(info, sizeof(info),
						    " tktuser %.100s",
						    client_user);

						packet_start(
						    SSH_SMSG_AUTH_KERBEROS_RESPONSE);
						packet_put_string((char *)
						    reply.dat, reply.length);
						packet_send();
						packet_write_wait();
					}
#endif /* KRB4 */
				} else {
#ifdef KRB5
					krb5_data tkt, reply;
					tkt.length = dlen;
					tkt.data = kdata;

					if (PRIVSEP(auth_krb5(authctxt, &tkt,
					    &client_user, &reply))) {
						authenticated = 1;
						snprintf(info, sizeof(info),
						    " tktuser %.100s",
						    client_user);

 						/* Send response to client */
 						packet_start(
						    SSH_SMSG_AUTH_KERBEROS_RESPONSE);
 						packet_put_string((char *)
						    reply.data, reply.length);
 						packet_send();
 						packet_write_wait();

 						if (reply.length)
 							xfree(reply.data);
					}
#endif /* KRB5 */
				}
				xfree(kdata);
			}
			break;
#endif /* KRB4 || KRB5 */

#if defined(AFS) || defined(KRB5)
			/* XXX - punt on backward compatibility here. */
		case SSH_CMSG_HAVE_KERBEROS_TGT:
			packet_send_debug("Kerberos TGT passing disabled before authentication.");
			break;
#ifdef AFS
		case SSH_CMSG_HAVE_AFS_TOKEN:
			packet_send_debug("AFS token passing disabled before authentication.");
			break;
#endif /* AFS */
#endif /* AFS || KRB5 */

		case SSH_CMSG_AUTH_RHOSTS:
			if (!options.rhosts_authentication) {
				verbose("Rhosts authentication disabled.");
				break;
			}
			/*
			 * Get client user name.  Note that we just have to
			 * trust the client; this is one reason why rhosts
			 * authentication is insecure. (Another is
			 * IP-spoofing on a local network.)
			 */
			client_user = packet_get_string(&ulen);
			packet_check_eom();

			/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
			authenticated = auth_rhosts(pw, client_user);

			snprintf(info, sizeof info, " ruser %.100s", client_user);
			break;

		case SSH_CMSG_AUTH_RHOSTS_RSA:
			if (!options.rhosts_rsa_authentication) {
				verbose("Rhosts with RSA authentication disabled.");
				break;
			}
			/*
			 * Get client user name.  Note that we just have to
			 * trust the client; root on the client machine can
			 * claim to be any user.
			 */
			client_user = packet_get_string(&ulen);

			/* Get the client host key. */
			client_host_key = key_new(KEY_RSA1);
			bits = packet_get_int();
			packet_get_bignum(client_host_key->rsa->e);
			packet_get_bignum(client_host_key->rsa->n);

			if (bits != BN_num_bits(client_host_key->rsa->n))
				verbose("Warning: keysize mismatch for client_host_key: "
				    "actual %d, announced %d",
				    BN_num_bits(client_host_key->rsa->n), bits);
			packet_check_eom();

			authenticated = auth_rhosts_rsa(pw, client_user,
			    client_host_key);
			key_free(client_host_key);

			snprintf(info, sizeof info, " ruser %.100s", client_user);
			break;

		case SSH_CMSG_AUTH_RSA:
			if (!options.rsa_authentication) {
				verbose("RSA authentication disabled.");
				break;
			}
			/* RSA authentication requested. */
			if ((n = BN_new()) == NULL)
				fatal("do_authloop: BN_new failed");
			packet_get_bignum(n);
			packet_check_eom();
			authenticated = auth_rsa(pw, n);
			BN_clear_free(n);
			break;

		case SSH_CMSG_AUTH_PASSWORD:
			if (!options.password_authentication) {
				verbose("Password authentication disabled.");
				break;
			}
			/*
			 * Read user password.  It is in plain text, but was
			 * transmitted over the encrypted channel so it is
			 * not visible to an outside observer.
			 */
			password = packet_get_string(&dlen);
			packet_check_eom();

			/* Try authentication with the password. */
			authenticated = PRIVSEP(auth_password(authctxt, password));

			memset(password, 0, strlen(password));
			xfree(password);
			break;

		case SSH_CMSG_AUTH_TIS:
			debug("rcvd SSH_CMSG_AUTH_TIS");
			if (options.challenge_response_authentication == 1) {
				char *challenge = get_challenge(authctxt);
				if (challenge != NULL) {
					debug("sending challenge '%s'", challenge);
					packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
					packet_put_cstring(challenge);
					xfree(challenge);
					packet_send();
					packet_write_wait();
					continue;
				}
			}
			break;
		case SSH_CMSG_AUTH_TIS_RESPONSE:
			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
			if (options.challenge_response_authentication == 1) {
				char *response = packet_get_string(&dlen);
				packet_check_eom();
				authenticated = verify_response(authctxt, response);
				memset(response, 'r', dlen);
				xfree(response);
			}
			break;

		default:
			/*
			 * Any unknown messages will be ignored (and failure
			 * returned) during authentication.
			 */
			logit("Unknown message during authentication: type %d", type);
			break;
		}
#ifdef BSD_AUTH
		if (authctxt->as) {
			auth_close(authctxt->as);
			authctxt->as = NULL;
		}
#endif
		if (!authctxt->valid && authenticated)
			fatal("INTERNAL ERROR: authenticated invalid user %s",
			    authctxt->user);

#ifdef _UNICOS
		if (authenticated && cray_access_denied(authctxt->user)) {
			authenticated = 0;
			fatal("Access denied for user %s.",authctxt->user);
		}
#endif /* _UNICOS */

#ifdef HAVE_CYGWIN
		if (authenticated &&
		    !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) {
			packet_disconnect("Authentication rejected for uid %d.",
			pw == NULL ? -1 : pw->pw_uid);
			authenticated = 0;
		}
#else
		/* Special handling for root */
		if (authenticated && authctxt->pw->pw_uid == 0 &&
		    !auth_root_allowed(get_authname(type)))
			authenticated = 0;
#endif
#ifdef USE_PAM
		if (!use_privsep && authenticated && 
		    !do_pam_account(pw->pw_name, client_user))
			authenticated = 0;
#endif

		/* Log before sending the reply */
		auth_log(authctxt, authenticated, get_authname(type), info);

		if (client_user != NULL) {
			xfree(client_user);
			client_user = NULL;
		}

		if (authenticated)
			return;

		if (authctxt->failures++ > AUTH_FAIL_MAX)
			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);

		packet_start(SSH_SMSG_FAILURE);
		packet_send();
		packet_write_wait();
	}
}

Project: openssh-portable

userauth_kbdint(Authctxt *authctxt)
{
	int authenticated = 0;
	char *lang, *devs;

	lang = packet_get_string(NULL);
	devs = packet_get_string(NULL);
	packet_check_eom();

	debug("keyboard-interactive devs %s", devs);

	if (options.challenge_response_authentication)
		authenticated = auth2_challenge(authctxt, devs);

	xfree(devs);
	xfree(lang);
#ifdef HAVE_CYGWIN
	if (check_nt_auth(0, authctxt->pw) == 0)
		return(0);
#endif
	return authenticated;
}

Project: openssh-portable

do_pam_chauthtok(void)
{
	struct pam_conv pam_conv = { pam_chauthtok_conv, NULL };

	if (use_privsep)
		fatal("PAM: chauthtok not supprted with privsep");
	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
	    (const void *)&pam_conv);
	if (sshpam_err != PAM_SUCCESS)
		fatal("PAM: failed to set PAM_CONV: %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	debug("PAM: changing password");
	sshpam_err = pam_chauthtok(sshpam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
	if (sshpam_err != PAM_SUCCESS)
		fatal("PAM: pam_chauthtok(): %s",
		    pam_strerror(sshpam_handle, sshpam_err));
}

Project: openssh-portable

pthread_join(sp_pthread_t thread, void **value __unused)
{
	int status;

	waitpid(thread, &status, 0);
	return (status);
}

Project: openssh-portable

mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
{
	Buffer m;
	u_char *blob;
	u_int len;
	int allowed = 0, have_forced = 0;

	debug3("%s entering", __func__);

	/* Convert the key to a blob and the pass it over */
	if (!key_to_blob(key, &blob, &len))
		return (0);

	buffer_init(&m);
	buffer_put_int(&m, type);
	buffer_put_cstring(&m, user ? user : "");
	buffer_put_cstring(&m, host ? host : "");
	buffer_put_string(&m, blob, len);
	xfree(blob);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);

	debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);

	allowed = buffer_get_int(&m);

	/* fake forced command */
	auth_clear_options();
	have_forced = buffer_get_int(&m);
	forced_command = have_forced ? xstrdup("true") : NULL;

	/* Send potential debug messages */
	mm_send_debug(&m);

	buffer_free(&m);

	return (allowed);
}

Project: openssh-portable

mm_auth_krb5(void *ctx, void *argp, char **userp, void *resp)
{
	krb5_data *tkt, *reply;
	Buffer m;
	int success;

	debug3("%s entering", __func__);
	tkt = (krb5_data *) argp;
	reply = (krb5_data *) resp;

	buffer_init(&m);
	buffer_put_string(&m, tkt->data, tkt->length);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5, &m);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5, &m);

	success = buffer_get_int(&m);
	if (success) {
		u_int len;

		*userp = buffer_get_string(&m, NULL);
		reply->data = buffer_get_string(&m, &len);
		reply->length = len;
	} else {
		memset(reply, 0, sizeof(*reply));
		*userp = NULL;
	}

	buffer_free(&m);
	return (success);
}

Project: openssh-portable

mm_answer_skeyquery(int socket, Buffer *m)
{
	struct skey skey;
	char challenge[1024];
	u_int success;

	success = skeychallenge(&skey, authctxt->user, challenge) < 0 ? 0 : 1;

	buffer_clear(m);
	buffer_put_int(m, success);
	if (success)
		buffer_put_cstring(m, challenge);

	debug3("%s: sending challenge success: %u", __func__, success);
	mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m);

	return (0);
}

Project: openssh-portable

monitor_reinit(struct monitor *mon)
{
	int pair[2];

	monitor_socketpair(pair);

	mon->m_recvfd = pair[0];
	mon->m_sendfd = pair[1];
}

Project: openssh-portable

mm_answer_skeyrespond(int socket, Buffer *m)
{
	char *response;
	int authok;

	response = buffer_get_string(m, NULL);

	authok = (options.challenge_response_authentication &&
	    authctxt->valid &&
	    skey_haskey(authctxt->pw->pw_name) == 0 &&
	    skey_passcheck(authctxt->pw->pw_name, response) != -1);

	xfree(response);

	buffer_clear(m);
	buffer_put_int(m, authok);

	debug3("%s: sending authenticated: %d", __func__, authok);
	mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m);

	auth_method = "skey";

	return (authok != 0);
}

Project: openssh-portable

mm_getpwnamallow(const char *login)
{
	Buffer m;
	struct passwd *pw;
	u_int pwlen;

	debug3("%s entering", __func__);

	buffer_init(&m);
	buffer_put_cstring(&m, login);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);

	debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);

	if (buffer_get_char(&m) == 0) {
		buffer_free(&m);
		return (NULL);
	}
	pw = buffer_get_string(&m, &pwlen);
	if (pwlen != sizeof(struct passwd))
		fatal("%s: struct passwd size mismatch", __func__);
	pw->pw_name = buffer_get_string(&m, NULL);
	pw->pw_passwd = buffer_get_string(&m, NULL);
	pw->pw_gecos = buffer_get_string(&m, NULL);
#ifdef HAVE_PW_CLASS_IN_PASSWD
	pw->pw_class = buffer_get_string(&m, NULL);
#endif
	pw->pw_dir = buffer_get_string(&m, NULL);
	pw->pw_shell = buffer_get_string(&m, NULL);
	buffer_free(&m);

	return (pw);
}

Project: openssh-portable

mm_answer_pam_init_ctx(int socket, Buffer *m)
{

	debug3("%s", __func__);
	authctxt->user = buffer_get_string(m, NULL);
	sshpam_ctxt = (sshpam_device.init_ctx)(authctxt);
	sshpam_authok = NULL;
	buffer_clear(m);
	if (sshpam_ctxt != NULL) {
		monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1);
		buffer_put_int(m, 1);
	} else {
		buffer_put_int(m, 0);
	}
	mm_request_send(socket, MONITOR_ANS_PAM_INIT_CTX, m);
	return (0);
}

Project: openssh-portable

input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
{
	Authctxt *authctxt = ctxt;
	KbdintAuthctxt *kbdintctxt;
	int i, authenticated = 0, res, len;
	u_int nresp;
	char **response = NULL, *method;

	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 */
	nresp = packet_get_int();
	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 = xmalloc(nresp * sizeof(char *));
		for (i = 0; i < nresp; i++)
			response[i] = packet_get_string(NULL);
	}
	packet_check_eom();

	if (authctxt->valid) {
		res = kbdintctxt->device->respond(kbdintctxt->ctxt,
		    nresp, response);
	} else {
		res = -1;
	}

	for (i = 0; i < nresp; i++) {
		memset(response[i], 'r', strlen(response[i]));
		xfree(response[i]);
	}
	if (response)
		xfree(response);

	switch (res) {
	case 0:
		/* Success! */
		authenticated = 1;
		break;
	case 1:
		/* Authentication needs further interaction */
		if (send_userauth_info_request(authctxt) == 1)
			authctxt->postponed = 1;
		break;
	default:
		/* Failure! */
		break;
	}

	len = strlen("keyboard-interactive") + 2 +
		strlen(kbdintctxt->device->name);
	method = xmalloc(len);
	snprintf(method, len, "keyboard-interactive/%s",
	    kbdintctxt->device->name);

	if (!authctxt->postponed) {
		if (authenticated) {
			auth2_challenge_stop(authctxt);
		} else {
			/* start next device */
			/* may set authctxt->postponed */
			auth2_challenge_start(authctxt);
		}
	}
	userauth_finish(authctxt, authenticated, method);
	xfree(method);
}

Project: openssh-portable

mm_answer_sesskey(int socket, Buffer *m)
{
	BIGNUM *p;
	int rsafail;

	/* Turn off permissions */
	monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);

	if ((p = BN_new()) == NULL)
		fatal("%s: BN_new", __func__);

	buffer_get_bignum2(m, p);

	rsafail = ssh1_session_key(p);

	buffer_clear(m);
	buffer_put_int(m, rsafail);
	buffer_put_bignum2(m, p);

	BN_clear_free(p);

	mm_request_send(socket, MONITOR_ANS_SESSKEY, m);

	/* Turn on permissions for sessid passing */
	monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);

	return (0);
}

Project: openssh-portable

monitor_apply_keystate(struct monitor *pmonitor)
{
	if (compat20) {
		set_newkeys(MODE_IN);
		set_newkeys(MODE_OUT);
	} else {
		packet_set_protocol_flags(child_state.ssh1protoflags);
		packet_set_encryption_key(child_state.ssh1key,
		    child_state.ssh1keylen, child_state.ssh1cipher);
		xfree(child_state.ssh1key);
	}

	/* for rc4 and other stateful ciphers */
	packet_set_keycontext(MODE_OUT, child_state.keyout);
	xfree(child_state.keyout);
	packet_set_keycontext(MODE_IN, child_state.keyin);
	xfree(child_state.keyin);

	if (!compat20) {
		packet_set_iv(MODE_OUT, child_state.ivout);
		xfree(child_state.ivout);
		packet_set_iv(MODE_IN, child_state.ivin);
		xfree(child_state.ivin);
	}

	memcpy(&incoming_stream, &child_state.incoming,
	    sizeof(incoming_stream));
	memcpy(&outgoing_stream, &child_state.outgoing,
	    sizeof(outgoing_stream));

	/* Update with new address */
	if (options.compression)
		mm_init_compression(pmonitor->m_zlib);

	/* Network I/O buffers */
	/* XXX inefficient for large buffers, need: buffer_init_from_string */
	buffer_clear(&input);
	buffer_append(&input, child_state.input, child_state.ilen);
	memset(child_state.input, 0, child_state.ilen);
	xfree(child_state.input);

	buffer_clear(&output);
	buffer_append(&output, child_state.output, child_state.olen);
	memset(child_state.output, 0, child_state.olen);
	xfree(child_state.output);
}

Project: openssh-portable

sshpam_null_conv(int n,
	 const struct pam_message **msg,
	 struct pam_response **resp,
	 void *data)
{

	return (PAM_CONV_ERR);
}

Project: openssh-portable

mm_auth_rsa_generate_challenge(Key *key)
{
	Buffer m;
	BIGNUM *challenge;
	u_char *blob;
	u_int blen;

	debug3("%s entering", __func__);

	if ((challenge = BN_new()) == NULL)
		fatal("%s: BN_new failed", __func__);

	key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
	if (key_to_blob(key, &blob, &blen) == 0)
		fatal("%s: key_to_blob failed", __func__);
	key->type = KEY_RSA1;

	buffer_init(&m);
	buffer_put_string(&m, blob, blen);
	xfree(blob);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);

	buffer_get_bignum2(&m, challenge);
	buffer_free(&m);

	return (challenge);
}

Project: openssh-portable

sshpam_free_ctx(void *ctxtp)
{
	struct pam_ctxt *ctxt = ctxtp;

	fatal_remove_cleanup(sshpam_thread_cleanup, ctxt);
	sshpam_thread_cleanup(ctxtp);
	xfree(ctxt);
	/*
	 * We don't call sshpam_cleanup() here because we may need the PAM
	 * handle at a later stage, e.g. when setting up a session.  It's
	 * still on the cleanup list, so pam_end() *will* be called before
	 * the server process terminates.
	 */
}

Project: openssh-portable

auth2_challenge(Authctxt *authctxt, char *devs)
{
	debug("auth2_challenge: user=%s devs=%s",
	    authctxt->user ? authctxt->user : "<nouser>",
	    devs ? devs : "<no devs>");

	if (authctxt->user == NULL || !devs)
		return 0;
	if (authctxt->kbdintctxt == NULL)
		authctxt->kbdintctxt = kbdint_alloc(devs);
	return auth2_challenge_start(authctxt);
}

Project: openssh-portable

mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
{
	Buffer m;
	char *p;
	int success = 0;

	buffer_init(&m);
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);

	debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);

	success = buffer_get_int(&m);
	if (success == 0) {
		debug3("%s: pty alloc failed", __func__);
		buffer_free(&m);
		return (0);
	}
	p = buffer_get_string(&m, NULL);
	buffer_free(&m);

	strlcpy(namebuf, p, namebuflen); /* Possible truncation */
	xfree(p);

	*ptyfd = mm_receive_fd(pmonitor->m_recvfd);
	*ttyfd = mm_receive_fd(pmonitor->m_recvfd);

	/* Success */
	return (1);
}

Project: openssh-portable

mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
{
	size_t len = (size_t) size * ncount;
	void *address;

	if (len == 0 || ncount > SIZE_T_MAX / size)
		fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size);

	address = mm_malloc(mm, len);

	return (address);
}

Project: openssh-portable

mm_start_pam(char *user)
{
	Buffer m;

	debug3("%s entering", __func__);

	buffer_init(&m);
	buffer_put_cstring(&m, user);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);

	buffer_free(&m);
}

Project: openssh-portable

mm_send_debug(Buffer *m)
{
	char *msg;

	while (buffer_len(m)) {
		msg = buffer_get_string(m, NULL);
		debug3("%s: Sending debug: %s", __func__, msg);
		packet_send_debug("%s", msg);
		xfree(msg);
	}
}

Project: openssh-portable

mm_send_keystate(struct monitor *pmonitor)
{
	Buffer m;
	u_char *blob, *p;
	u_int bloblen, plen;
	u_int32_t seqnr, packets;
	u_int64_t blocks;

	buffer_init(&m);

	if (!compat20) {
		u_char iv[24];
		u_char *key;
		u_int ivlen, keylen;

		buffer_put_int(&m, packet_get_protocol_flags());

		buffer_put_int(&m, packet_get_ssh1_cipher());

		debug3("%s: Sending ssh1 KEY+IV", __func__);
		keylen = packet_get_encryption_key(NULL);
		key = xmalloc(keylen+1);	/* add 1 if keylen == 0 */
		keylen = packet_get_encryption_key(key);
		buffer_put_string(&m, key, keylen);
		memset(key, 0, keylen);
		xfree(key);

		ivlen = packet_get_keyiv_len(MODE_OUT);
		packet_get_keyiv(MODE_OUT, iv, ivlen);
		buffer_put_string(&m, iv, ivlen);
		ivlen = packet_get_keyiv_len(MODE_OUT);
		packet_get_keyiv(MODE_IN, iv, ivlen);
		buffer_put_string(&m, iv, ivlen);
		goto skip;
	} else {
		/* Kex for rekeying */
		mm_send_kex(&m, *pmonitor->m_pkex);
	}

	debug3("%s: Sending new keys: %p %p",
	    __func__, newkeys[MODE_OUT], newkeys[MODE_IN]);

	/* Keys from Kex */
	if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
		fatal("%s: conversion of newkeys failed", __func__);

	buffer_put_string(&m, blob, bloblen);
	xfree(blob);

	if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
		fatal("%s: conversion of newkeys failed", __func__);

	buffer_put_string(&m, blob, bloblen);
	xfree(blob);

	packet_get_state(MODE_OUT, &seqnr, &blocks, &packets);
	buffer_put_int(&m, seqnr);
	buffer_put_int64(&m, blocks);
	buffer_put_int(&m, packets);
	packet_get_state(MODE_IN, &seqnr, &blocks, &packets);
	buffer_put_int(&m, seqnr);
	buffer_put_int64(&m, blocks);
	buffer_put_int(&m, packets);

	debug3("%s: New keys have been sent", __func__);
 skip:
	/* More key context */
	plen = packet_get_keycontext(MODE_OUT, NULL);
	p = xmalloc(plen+1);
	packet_get_keycontext(MODE_OUT, p);
	buffer_put_string(&m, p, plen);
	xfree(p);

	plen = packet_get_keycontext(MODE_IN, NULL);
	p = xmalloc(plen+1);
	packet_get_keycontext(MODE_IN, p);
	buffer_put_string(&m, p, plen);
	xfree(p);

	/* Compression state */
	debug3("%s: Sending compression state", __func__);
	buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
	buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));

	/* Network I/O buffers */
	buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
	buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
	debug3("%s: Finished sending state", __func__);

	buffer_free(&m);
}

Project: openssh-portable

mm_answer_moduli(int socket, Buffer *m)
{
	DH *dh;
	int min, want, max;

	min = buffer_get_int(m);
	want = buffer_get_int(m);
	max = buffer_get_int(m);

	debug3("%s: got parameters: %d %d %d",
	    __func__, min, want, max);
	/* We need to check here, too, in case the child got corrupted */
	if (max < min || want < min || max < want)
		fatal("%s: bad parameters: %d %d %d",
		    __func__, min, want, max);

	buffer_clear(m);

	dh = choose_dh(min, want, max);
	if (dh == NULL) {
		buffer_put_char(m, 0);
		return (0);
	} else {
		/* Send first bignum */
		buffer_put_char(m, 1);
		buffer_put_bignum2(m, dh->p);
		buffer_put_bignum2(m, dh->g);

		DH_free(dh);
	}
	mm_request_send(socket, MONITOR_ANS_MODULI, m);
	return (0);
}

Project: openssh-portable

monitor_allowed_key(u_char *blob, u_int bloblen)
{
	/* make sure key is allowed */
	if (key_blob == NULL || key_bloblen != bloblen ||
	    memcmp(key_blob, blob, key_bloblen))
		return (0);
	return (1);
}

Project: openssh-portable

sshpam_init(const char *user)
{
	extern ServerOptions options;
	extern u_int utmp_len;
	const char *pam_rhost, *pam_user;

	if (sshpam_handle != NULL) {
		/* We already have a PAM context; check if the user matches */
		sshpam_err = pam_get_item(sshpam_handle,
		    PAM_USER, (const void **)&pam_user);
		if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
			return (0);
		fatal_remove_cleanup(sshpam_cleanup, NULL);
		pam_end(sshpam_handle, sshpam_err);
		sshpam_handle = NULL;
	}
	debug("PAM: initializing for \"%s\"", user);
	sshpam_err = pam_start("sshd", user, &null_conv, &sshpam_handle);
	if (sshpam_err != PAM_SUCCESS)
		return (-1);
	pam_rhost = get_remote_name_or_ip(utmp_len,
	    options.verify_reverse_mapping);
	debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
	sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
	if (sshpam_err != PAM_SUCCESS) {
		pam_end(sshpam_handle, sshpam_err);
		sshpam_handle = NULL;
		return (-1);
	}
	fatal_add_cleanup(sshpam_cleanup, NULL);
	return (0);
}

Project: openssh-portable

mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
{
	Kex *kex = *pmonitor->m_pkex;
	Buffer m;

	debug3("%s entering", __func__);

	buffer_init(&m);
	buffer_put_int(&m, kex->host_key_index(key));
	buffer_put_string(&m, data, datalen);

	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);

	debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
	*sigp  = buffer_get_string(&m, lenp);
	buffer_free(&m);

	return (0);
}

Project: openssh-portable

fetch_pam_environment(void)
{
#ifdef HAVE_PAM_GETENVLIST
	debug("PAM: retrieving environment");
	return (pam_getenvlist(sshpam_handle));
#else
	return (NULL);
#endif
}

Project: openssh-portable

mm_answer_authserv(int socket, Buffer *m)
{
	monitor_permit_authentications(1);

	authctxt->service = buffer_get_string(m, NULL);
	authctxt->style = buffer_get_string(m, NULL);
	debug3("%s: service=%s, style=%s",
	    __func__, authctxt->service, authctxt->style);

	if (strlen(authctxt->style) == 0) {
		xfree(authctxt->style);
		authctxt->style = NULL;
	}

	return (0);
}

Project: openssh-portable

mm_answer_bsdauthrespond(int socket, Buffer *m)
{
	char *response;
	int authok;

	if (authctxt->as == 0)
		fatal("%s: no bsd auth session", __func__);

	response = buffer_get_string(m, NULL);
	authok = options.challenge_response_authentication &&
	    auth_userresponse(authctxt->as, response, 0);
	authctxt->as = NULL;
	debug3("%s: <%s> = <%d>", __func__, response, authok);
	xfree(response);

	buffer_clear(m);
	buffer_put_int(m, authok);

	debug3("%s: sending authenticated: %d", __func__, authok);
	mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m);

	auth_method = "bsdauth";

	return (authok != 0);
}