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); }
void mm_inform_authrole(char *role) { Buffer m; debug3("%s entering", __func__); buffer_init(&m); buffer_put_cstring(&m, role ? role : ""); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m); buffer_free(&m); }
void auth_debug_add(const char *fmt,...) { char buf[1024]; va_list args; if (!auth_debug_init) return; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); buffer_put_cstring(&auth_debug, buf); }
int 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; buffer_free(&m); return (allowed); }
int ssh_rename(const char *oldname, const char *newname) { Buffer msg; u_int status, id; char *on, *nn; buffer_init(&msg); on = ftp_path_absolute(oldname); nn = ftp_path_absolute(newname); stripslash(on); stripslash(nn); /* Send rename request */ id = ftp->ssh_id++; buffer_put_char(&msg, SSH2_FXP_RENAME); buffer_put_int(&msg, id); buffer_put_cstring(&msg, on); buffer_put_cstring(&msg, nn); ssh_cmd( &msg); buffer_free(&msg); status = ssh_get_status(id); if(status != SSH2_FX_OK) { ftp_err("Couldn't rename file \"%s\" to \"%s\": %s\n", on, nn, fx2txt(status)); free(on); free(nn); return -1; } ftp_cache_flush_mark_for(on); ftp_cache_flush_mark_for(nn); free(on); free(nn); return 0; }
int ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { ECDSA_SIG *sig; const EVP_MD *evp_md; EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE]; u_int len, dlen; Buffer b, bb; if (key == NULL || key->ecdsa == NULL || (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) { error("%s: no ECDSA key", __func__); return -1; } evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid); EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); sig = ECDSA_do_sign(digest, dlen, key->ecdsa); memset(digest, 'd', sizeof(digest)); if (sig == NULL) { error("%s: sign failed", __func__); return -1; } buffer_init(&bb); buffer_put_bignum2(&bb, sig->r); buffer_put_bignum2(&bb, sig->s); ECDSA_SIG_free(sig); buffer_init(&b); buffer_put_cstring(&b, key_ssh_name_plain(key)); buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb)); buffer_free(&bb); len = buffer_len(&b); if (lenp != NULL) *lenp = len; if (sigp != NULL) { *sigp = xmalloc(len); memcpy(*sigp, buffer_ptr(&b), len); } buffer_free(&b); return 0; }
int pkcs11_add_provider(char *name, char *pin, Key ***keysp) { Key *k; int i, nkeys; u_char *blob; u_int blen; Buffer msg; if (fd < 0 && pkcs11_start_helper() < 0) return (-1); buffer_init(&msg); buffer_put_char(&msg, SSH_AGENTC_ADD_SMARTCARD_KEY); buffer_put_cstring(&msg, name); buffer_put_cstring(&msg, pin); send_msg(&msg); buffer_clear(&msg); if (recv_msg(&msg) == SSH2_AGENT_IDENTITIES_ANSWER) { nkeys = buffer_get_int(&msg); *keysp = xcalloc(nkeys, sizeof(Key *)); for (i = 0; i < nkeys; i++) { blob = buffer_get_string(&msg, &blen); free(buffer_get_string(&msg, NULL)); k = key_from_blob(blob, blen); wrap_key(k->rsa); (*keysp)[i] = k; free(blob); } } else { nkeys = -1; } buffer_free(&msg); return (nkeys); }
int ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id, const char *pin, u_int life, u_int confirm) { Buffer msg; int type, constrained = (life || confirm); if (add) { type = constrained ? SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED : SSH_AGENTC_ADD_SMARTCARD_KEY; } else type = SSH_AGENTC_REMOVE_SMARTCARD_KEY; buffer_init(&msg); buffer_put_char(&msg, type); buffer_put_cstring(&msg, reader_id); buffer_put_cstring(&msg, pin); if (constrained) { if (life != 0) { buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); buffer_put_int(&msg, life); } if (confirm != 0) buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM); } if (ssh_request_reply(auth, &msg, &msg) == 0) { buffer_free(&msg); return 0; } type = buffer_get_char(&msg); buffer_free(&msg); return decode_reply(type); }
struct passwd * mm_getpwnamallow(const char *username) { Buffer m; struct passwd *pw; u_int len; ServerOptions *newopts; debug3("%s entering", __func__); buffer_init(&m); buffer_put_cstring(&m, username); 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) { pw = NULL; goto out; } pw = buffer_get_string(&m, &len); if (len != 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); out: /* copy options block as a Match directive may have changed some */ newopts = buffer_get_string(&m, &len); if (len != sizeof(*newopts)) fatal("%s: option block size mismatch", __func__); if (newopts->banner != NULL) newopts->banner = buffer_get_string(&m, NULL); copy_set_server_options(&options, newopts, 1); xfree(newopts); buffer_free(&m); return (pw); }
void mm_start_pam(char *user) { Buffer m; debug3("%s entering", __func__); if (!options.use_pam) fatal("UsePAM=no, but ended up in %s anyway", __func__); buffer_init(&m); buffer_put_cstring(&m, user); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m); buffer_free(&m); }
int ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { u_char *sig; u_int slen, len; unsigned long long smlen; int ret; Buffer b; if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || key->ed25519_sk == NULL) { error("%s: no ED25519 key", __func__); return -1; } if (datalen >= UINT_MAX - crypto_sign_ed25519_BYTES) { error("%s: datalen %u too long", __func__, datalen); return -1; } smlen = slen = datalen + crypto_sign_ed25519_BYTES; sig = xmalloc(slen); if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, key->ed25519_sk)) != 0 || smlen <= datalen) { error("%s: crypto_sign_ed25519 failed: %d", __func__, ret); free(sig); return -1; } /* encode signature */ buffer_init(&b); buffer_put_cstring(&b, "ssh-ed25519"); buffer_put_string(&b, sig, smlen - datalen); len = buffer_len(&b); if (lenp != NULL) *lenp = len; if (sigp != NULL) { *sigp = xmalloc(len); memcpy(*sigp, buffer_ptr(&b), len); } buffer_free(&b); explicit_bzero(sig, slen); free(sig); return 0; }
/* put algorithm proposal into buffer */ static void kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) { int i; buffer_clear(b); /* * add a dummy cookie, the cookie will be overwritten by * kex_send_kexinit(), each time a kexinit is set */ for (i = 0; i < KEX_COOKIE_LEN; i++) buffer_put_char(b, 0); for (i = 0; i < PROPOSAL_MAX; i++) buffer_put_cstring(b, proposal[i]); buffer_put_char(b, 0); /* first_kex_packet_follows */ buffer_put_int(b, 0); /* uint32 reserved */ }
/* * Derive fake salt as H(username || first_private_host_key) * This provides relatively stable fake salts for non-existent * users and avoids the jpake method becoming an account validity * oracle. */ static void derive_rawsalt(const char *username, u_char *rawsalt, u_int len) { u_char *digest; u_int digest_len; Buffer b; Key *k; buffer_init(&b); buffer_put_cstring(&b, username); if ((k = get_hostkey_by_index(0)) == NULL || (k->flags & KEY_FLAG_EXT)) fatal("%s: no hostkeys", __func__); switch (k->type) { case KEY_RSA1: case KEY_RSA: if (k->rsa->p == NULL || k->rsa->q == NULL) fatal("%s: RSA key missing p and/or q", __func__); buffer_put_bignum2(&b, k->rsa->p); buffer_put_bignum2(&b, k->rsa->q); break; case KEY_DSA: if (k->dsa->priv_key == NULL) fatal("%s: DSA key missing priv_key", __func__); buffer_put_bignum2(&b, k->dsa->priv_key); break; case KEY_ECDSA: if (EC_KEY_get0_private_key(k->ecdsa) == NULL) fatal("%s: ECDSA key missing priv_key", __func__); buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa)); break; default: fatal("%s: unknown key type %d", __func__, k->type); } if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(), &digest, &digest_len) != 0) fatal("%s: hash_buffer", __func__); buffer_free(&b); if (len > digest_len) fatal("%s: not enough bytes for rawsalt (want %u have %u)", __func__, len, digest_len); memcpy(rawsalt, digest, len); bzero(digest, digest_len); free(digest); }
struct shaft_conn * do_init(int fd_in, int fd_out, struct shaft_flow *flow) { u_int type, version; Buffer msg; struct shaft_conn *ret; buffer_init(&msg); buffer_put_char(&msg, SHAFT_INIT); buffer_put_int(&msg, SHAFT_VERSION); buffer_put_cstring(&msg, flow->local); send_msg(fd_out, &msg); buffer_clear(&msg); get_msg(fd_in, &msg); /* Expecting a VERSION reply */ if ((type = buffer_get_char(&msg)) != SHAFT_VERSION) { error("Invalid packet back from SHAFT_INIT (type %u)", version); buffer_free(&msg); return(NULL); } version = buffer_get_int(&msg); flow->dst = buffer_get_cstring(&msg, NULL); if (flow->dst == NULL) { error("Invalid packet back from SHAFT_INIT remote addr is null"); buffer_free(&msg); return(NULL); } debug2("Remote version: %u", version); debug2("Remote Address: %s", flow->dst); buffer_free(&msg); ret = xmalloc(sizeof(*ret)); ret->fd_in = fd_in; ret->fd_out = fd_out; ret->version = version; ret->msg_id = 1; return(ret); }
/* Lock/unlock agent */ int ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password) { int type; Buffer msg; buffer_init(&msg); buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK); buffer_put_cstring(&msg, password); if (ssh_request_reply(auth, &msg, &msg) == 0) { buffer_free(&msg); return 0; } type = buffer_get_char(&msg); buffer_free(&msg); return decode_reply(type); }
int mm_answer_skeyquery(int socket, Buffer *m) { struct skey skey; char challenge[1024]; int res; res = skeychallenge(&skey, authctxt->user, challenge); buffer_clear(m); buffer_put_int(m, res); if (res != -1) buffer_put_cstring(m, challenge); debug3("%s: sending challenge res: %d", __func__, res); mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m); return (0); }
int 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); }
int 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); }
int 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); }
void mm_session_pty_cleanup2(Session *s) { 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 (s->ptymaster != -1 && close(s->ptymaster) < 0) error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); /* unlink pty from session */ s->ttyfd = -1; }
static void send_rexec_state(int fd, Buffer *conf) { Buffer m; debug3("%s: entering fd = %d config len %d", __func__, fd, buffer_len(conf)); /* * Protocol from reexec master to child: * string configuration * u_int ephemeral_key_follows * bignum e (only if ephemeral_key_follows == 1) * bignum n " * bignum d " * bignum iqmp " * bignum p " * bignum q " */ buffer_init(&m); buffer_put_cstring(&m, buffer_ptr(conf)); if (sensitive_data.server_key != NULL && sensitive_data.server_key->type == KEY_RSA1) { buffer_put_int(&m, 1); buffer_put_bignum(&m, sensitive_data.server_key->rsa->e); buffer_put_bignum(&m, sensitive_data.server_key->rsa->n); buffer_put_bignum(&m, sensitive_data.server_key->rsa->d); buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp); buffer_put_bignum(&m, sensitive_data.server_key->rsa->p); buffer_put_bignum(&m, sensitive_data.server_key->rsa->q); } else buffer_put_int(&m, 0); if (ssh_msg_send(fd, 0, &m) == -1) fatal("%s: ssh_msg_send failed", __func__); buffer_free(&m); debug3("%s: done", __func__); }
void * mm_sshpam_init_ctx(Authctxt *authctxt) { Buffer m; int success; debug3("%s", __func__); buffer_init(&m); buffer_put_cstring(&m, authctxt->user); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m); debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m); success = buffer_get_int(&m); if (success == 0) { debug3("%s: pam_init_ctx failed", __func__); buffer_free(&m); return (NULL); } buffer_free(&m); return (authctxt); }
int packet_fxp_open(Buffer *buff, Buffer *preped_buff) { u_int msg_len; u_int xmsg_len; // File names u_int file_len, pflags; u_char *filename; // Copy first part of packet over to prepared buffer msg_len = get_u32(buffer_ptr(buff)); xmsg_len = msg_len; buffer_append(preped_buff, buffer_ptr(buff), 9); buffer_consume(buff, 9); xmsg_len -= 5; // Rewrite path filename = buffer_get_string(buff, &file_len); filename = unchroot_filename(filename, (u_char*) user_homedir); buffer_put_cstring(preped_buff, (char*) filename); xmsg_len -= (file_len + 4); msg_len += (strlen((char*) filename) - file_len); // pflags pflags = buffer_get_int(buff); buffer_put_int(preped_buff, pflags); xmsg_len -= 4; // Copy attributes through, cleaning extensions where required parse_attrs(buff, preped_buff, &msg_len, &xmsg_len); // Copy any remaining packet data over buffer_append(preped_buff, buffer_ptr(buff), xmsg_len); buffer_consume(buff, xmsg_len); // Rewrite message length put_u32(buffer_end(preped_buff)-msg_len-4, msg_len); return 1; }
int mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) { Buffer m; int authok; debug3("%s: entering", __func__); if (numresponses != 1) return (-1); buffer_init(&m); buffer_put_cstring(&m, responses[0]); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHRESPOND, &m); authok = buffer_get_int(&m); buffer_free(&m); return ((authok == 0) ? -1 : 0); }
/* Do the password authentication */ int mm_auth_password(Authctxt *authctxt, char *password) { Buffer m; int authenticated = 0; debug3("%s entering", __func__); buffer_init(&m); buffer_put_cstring(&m, password); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m); debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m); authenticated = buffer_get_int(&m); buffer_free(&m); debug3("%s: user %sauthenticated", __func__, authenticated ? "" : "not "); return (authenticated); }
int mm_key_sign(struct sshkey *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen, const char *hostkey_alg) { struct kex *kex = *pmonitor->m_pkex; Buffer m; debug3("%s entering", __func__); buffer_init(&m); buffer_put_int(&m, kex->host_key_index(key, 0, active_state)); buffer_put_string(&m, data, datalen); buffer_put_cstring(&m, hostkey_alg); 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); }
struct passwd * 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); }
static void process_init(void) { Buffer msg; version = get_int(); verbose("received client version %d", version); buffer_init(&msg); buffer_put_char(&msg, SSH2_FXP_VERSION); buffer_put_int(&msg, SSH2_FILEXFER_VERSION); /* POSIX rename extension */ buffer_put_cstring(&msg, "*****@*****.**"); buffer_put_cstring(&msg, "1"); /* version */ /* statvfs extension */ buffer_put_cstring(&msg, "*****@*****.**"); buffer_put_cstring(&msg, "2"); /* version */ /* fstatvfs extension */ buffer_put_cstring(&msg, "*****@*****.**"); buffer_put_cstring(&msg, "2"); /* version */ send_msg(&msg); buffer_free(&msg); }
int mm_answer_pwnamallow(int sock, Buffer *m) { char *username; struct passwd *pwent; int allowed = 0; debug3("%s", __func__); if (authctxt->attempt++ != 0) fatal("%s: multiple attempts for getpwnam", __func__); username = buffer_get_string(m, NULL); pwent = getpwnamallow(username); authctxt->user = xstrdup(username); setproctitle("%s [priv]", pwent ? username : "******"); xfree(username); buffer_clear(m); if (pwent == NULL) { buffer_put_char(m, 0); authctxt->pw = fakepw(); 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(sock, 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 if (options.use_pam) monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); #endif #ifdef SSH_AUDIT_EVENTS monitor_permit(mon_dispatch, MONITOR_REQ_AUDIT_COMMAND, 1); #endif return (0); }
int mm_answer_pty(int sock, 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; pty_setowner(authctxt->pw, s->tty); buffer_put_int(m, 1); buffer_put_cstring(m, s->tty); /* 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); /* send messages generated by record_login */ buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg)); buffer_clear(&loginmsg); mm_request_send(sock, MONITOR_ANS_PTY, m); mm_send_fd(sock, s->ptyfd); mm_send_fd(sock, s->ttyfd); /* 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(sock, MONITOR_ANS_PTY, m); return (0); }