struct passwd * mm_getpwnamallow(const char *username) { Buffer m; struct passwd *pw; u_int len, i; 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__); #define M_CP_STROPT(x) do { \ if (newopts->x != NULL) \ newopts->x = buffer_get_string(&m, NULL); \ } while (0) #define M_CP_STRARRAYOPT(x, nx) do { \ for (i = 0; i < newopts->nx; i++) \ newopts->x[i] = buffer_get_string(&m, NULL); \ } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT #undef M_CP_STRARRAYOPT copy_set_server_options(&options, newopts, 1); xfree(newopts); buffer_free(&m); return (pw); }
int mm_answer_pwnamallow(int sock, struct sshbuf *m) { char *username; struct passwd *pwent; int r, allowed = 0; u_int i; debug3("%s", __func__); if (authctxt->attempt++ != 0) fatal("%s: multiple attempts for getpwnam", __func__); if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); pwent = getpwnamallow(username); authctxt->user = xstrdup(username); setproctitle("%s [priv]", pwent ? username : "******"); free(username); sshbuf_reset(m); if (pwent == NULL) { if ((r = sshbuf_put_u8(m, 0)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); authctxt->pw = fakepw(); goto out; } allowed = 1; authctxt->pw = pwent; authctxt->valid = 1; if ((r = sshbuf_put_u8(m, 1)) != 0 || (r = sshbuf_put_string(m, pwent, sizeof(struct passwd))) != 0 || (r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 || (r = sshbuf_put_cstring(m, "*")) != 0 || (r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 || (r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 || (r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 || (r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); out: if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); #define M_CP_STROPT(x) do { \ if (options.x != NULL) \ if ((r = sshbuf_put_cstring(m, options.x)) != 0) \ fatal("%s: buffer error: %s", __func__, \ ssh_err(r)); \ } while (0) #define M_CP_STRARRAYOPT(x, nx) do { \ for (i = 0; i < options.nx; i++) \ if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \ fatal("%s: buffer error: %s", __func__, \ ssh_err(r)); \ } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT #undef M_CP_STRARRAYOPT /* Create valid auth method lists */ if (compat20 && auth2_setup_methods_lists(authctxt) != 0) { /* * The monitor will continue long enough to let the child * run to it's packet_disconnect(), but it must not allow any * authentication to succeed. */ debug("%s: no valid authentication method lists", __func__); } 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); } return (0); }
int mm_answer_pwnamallow(int sock, Buffer *m) { struct ssh *ssh = active_state; /* XXX */ char *username; struct passwd *pwent; int allowed = 0; u_int i; 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 : "******"); free(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, "*"); #ifdef HAVE_STRUCT_PASSWD_PW_GECOS buffer_put_cstring(m, pwent->pw_gecos); #endif #ifdef HAVE_STRUCT_PASSWD_PW_CLASS buffer_put_cstring(m, pwent->pw_class); #endif buffer_put_cstring(m, pwent->pw_dir); buffer_put_cstring(m, pwent->pw_shell); out: ssh_packet_set_log_preamble(ssh, "%suser %s", authctxt->valid ? "authenticating" : "invalid ", authctxt->user); buffer_put_string(m, &options, sizeof(options)); #define M_CP_STROPT(x) do { \ if (options.x != NULL) \ buffer_put_cstring(m, options.x); \ } while (0) #define M_CP_STRARRAYOPT(x, nx) do { \ for (i = 0; i < options.nx; i++) \ buffer_put_cstring(m, options.x[i]); \ } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT #undef M_CP_STRARRAYOPT /* Create valid auth method lists */ if (auth2_setup_methods_lists(authctxt) != 0) { /* * The monitor will continue long enough to let the child * run to it's packet_disconnect(), but it must not allow any * authentication to succeed. */ debug("%s: no valid authentication method lists", __func__); } debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); mm_request_send(sock, MONITOR_ANS_PWNAM, m); /* 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 return (0); }