コード例 #1
0
ファイル: pamsrv_cmd.c プロジェクト: nalind/sssd
static void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
                                    time_t expire_date, time_t delayed_until)
{
    uint32_t resp_type;
    size_t resp_len;
    uint8_t *resp;
    int64_t dummy;

    preq->pd->pam_status = cached_login_pam_status(ret);

    switch (preq->pd->pam_status) {
        case PAM_SUCCESS:
            resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH;
            resp_len = sizeof(uint32_t) + sizeof(int64_t);
            resp = talloc_size(preq->pd, resp_len);
            if (resp == NULL) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      "talloc_size failed, cannot prepare user info.\n");
            } else {
                memcpy(resp, &resp_type, sizeof(uint32_t));
                dummy = (int64_t) expire_date;
                memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t));
                ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
                                       (const uint8_t *) resp);
                if (ret != EOK) {
                    DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
                }
            }
            break;
        case PAM_PERM_DENIED:
            if (delayed_until >= 0) {
                resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED;
                resp_len = sizeof(uint32_t) + sizeof(int64_t);
                resp = talloc_size(preq->pd, resp_len);
                if (resp == NULL) {
                    DEBUG(SSSDBG_CRIT_FAILURE,
                          "talloc_size failed, cannot prepare user info.\n");
                } else {
                    memcpy(resp, &resp_type, sizeof(uint32_t));
                    dummy = (int64_t) delayed_until;
                    memcpy(resp+sizeof(uint32_t), &dummy, sizeof(int64_t));
                    ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
                                           (const uint8_t *) resp);
                    if (ret != EOK) {
                        DEBUG(SSSDBG_CRIT_FAILURE,
                              "pam_add_response failed.\n");
                    }
                }
            }
            break;
        default:
            DEBUG(SSSDBG_TRACE_LIBS,
                  "cached login returned: %d\n", preq->pd->pam_status);
    }

    pam_reply(preq);
    return;
}
コード例 #2
0
ファイル: ldap_auth.c プロジェクト: SSSD/sssd
static errno_t add_expired_warning(struct pam_data *pd, long exp_time)
{
    int ret;
    uint32_t *data;

    if (exp_time < 0 || exp_time > UINT32_MAX) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Time to expire out of range.\n");
        return EINVAL;
    }

    data = talloc_array(pd, uint32_t, 2);
    if (data == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
        return ENOMEM;
    }

    data[0] = SSS_PAM_USER_INFO_EXPIRE_WARN;
    data[1] = (uint32_t) exp_time;

    ret = pam_add_response(pd, SSS_PAM_USER_INFO, 2 * sizeof(uint32_t),
                           (uint8_t *) data);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
    }

    return EOK;
}
コード例 #3
0
ファイル: ldap_auth.c プロジェクト: SSSD/sssd
static errno_t check_pwexpire_ldap(struct pam_data *pd,
                                   struct sdap_ppolicy_data *ppolicy,
                                   int pwd_exp_warning)
{
    int ret = EOK;

    if (ppolicy->grace >= 0 || ppolicy->expire > 0) {
        uint32_t *data;
        uint32_t *ptr;

        if (pwd_exp_warning < 0) {
            pwd_exp_warning = 0;
        }

        data = talloc_size(pd, 2* sizeof(uint32_t));
        if (data == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
            return ENOMEM;
        }

        ptr = data;
        if (ppolicy->grace >= 0) {
            *ptr = SSS_PAM_USER_INFO_GRACE_LOGIN;
            ptr++;
            *ptr = ppolicy->grace;
        } else if (ppolicy->expire > 0) {
            if (pwd_exp_warning != 0 && ppolicy->expire > pwd_exp_warning) {
                /* do not warn */
                goto done;
            }

            /* send warning */
            *ptr = SSS_PAM_USER_INFO_EXPIRE_WARN;
            ptr++;
            *ptr = ppolicy->expire;
        }

        ret = pam_add_response(pd, SSS_PAM_USER_INFO, 2* sizeof(uint32_t),
                               (uint8_t*)data);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
        }
    }

done:
    return ret;
}
コード例 #4
0
ファイル: pam_prompting_config.c プロジェクト: SSSD/sssd
errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd)
{
    int ret;
    struct response_data *resp;
    bool password_auth = false;
    bool otp_auth = false;
    bool cert_auth = false;
    struct prompt_config **pc_list = NULL;
    int resp_len;
    uint8_t *resp_data = NULL;

    if (pctx->num_prompting_config_sections == 0) {
        DEBUG(SSSDBG_TRACE_ALL, "No prompting configuration found.\n");
        return EOK;
    }

    resp = pd->resp_list;
    while (resp != NULL) {
        switch (resp->type) {
        case SSS_PAM_OTP_INFO:
            otp_auth = true;
            break;
        case SSS_PAM_CERT_INFO:
            cert_auth = true;
            break;
        case SSS_PASSWORD_PROMPTING:
            password_auth = true;
            break;
        case SSS_CERT_AUTH_PROMPTING:
            /* currently not used */
            break;
        default:
            break;
        }
        resp = resp->next;
    }

    if (!password_auth && !otp_auth && !cert_auth) {
        /* If the backend cannot determine which authentication types are
         * available the default would be to prompt for a password. */
        password_auth = true;
    }

    DEBUG(SSSDBG_TRACE_ALL, "Authentication types for user [%s] and service "
                            "[%s]:%s%s%s\n", pd->user, pd->service,
                            password_auth ? " password": "",
                            otp_auth ? " two-factor" : "",
                            cert_auth ? " smartcard" : "");

    if (cert_auth) {
        /* If certificate based authentication is possilbe, i.e. a Smartcard
         * or similar with the mapped certificate is available we currently
         * prefer this authentication type unconditionally. If other types
         * should be used the Smartcard can be removed during authentication.
         * Since there currently are no specific options for cert_auth we are
         * done. */
        ret = EOK;
        goto done;
    }

    /* If OTP and password auth are possible we currently prefer OTP. */
    if (otp_auth) {
        ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service,
                                        pctx->prompting_config_sections,
                                        pctx->num_prompting_config_sections,
                                        CONFDB_PC_TYPE_2FA,
                                        pam_set_2fa_prompting_options,
                                        &pc_list);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  "pam_set_prompting_options failed.\n");
            goto done;
        }
    }

    if (password_auth) {
        ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service,
                                        pctx->prompting_config_sections,
                                        pctx->num_prompting_config_sections,
                                        CONFDB_PC_TYPE_PASSWORD,
                                        pam_set_password_prompting_options,
                                        &pc_list);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  "pam_set_prompting_options failed.\n");
            goto done;
        }
    }

    if (pc_list != NULL) {
        ret = pam_get_response_prompt_config(pc_list, &resp_len, &resp_data);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  "pam_get_response_prompt_config failed.\n");
            goto done;
        }

        ret = pam_add_response(pd, SSS_PAM_PROMPT_CONFIG, resp_len, resp_data);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE, "pam_add_response failed.\n");
            goto done;
        }
    }

    ret = EOK;
done:
    free(resp_data);
    pc_list_free(pc_list);

    return ret;
}
コード例 #5
0
ファイル: pamsrv_cmd.c プロジェクト: nalind/sssd
static void pam_reply(struct pam_auth_req *preq)
{
    struct cli_ctx *cctx;
    uint8_t *body;
    size_t blen;
    int ret;
    int32_t resp_c;
    int32_t resp_size;
    struct response_data *resp;
    int p;
    struct timeval tv;
    struct tevent_timer *te;
    struct pam_data *pd;
    struct pam_ctx *pctx;
    uint32_t user_info_type;
    time_t exp_date = -1;
    time_t delay_until = -1;

    pd = preq->pd;
    cctx = preq->cctx;
    pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);


    DEBUG(SSSDBG_FUNC_DATA,
          "pam_reply called with result [%d].\n", pd->pam_status);

    if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
        switch(pd->cmd) {
        case SSS_PAM_AUTHENTICATE:
            if ((preq->domain != NULL) &&
                (preq->domain->cache_credentials == true) &&
                (pd->offline_auth == false)) {
                const char *password = NULL;

                /* do auth with offline credentials */
                pd->offline_auth = true;

                if (preq->domain->sysdb == NULL) {
                    DEBUG(SSSDBG_FATAL_FAILURE,
                          "Fatal: Sysdb CTX not found for domain"
                              " [%s]!\n", preq->domain->name);
                    goto done;
                }

                ret = sss_authtok_get_password(pd->authtok, &password, NULL);
                if (ret) {
                    DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
                    goto done;
                }

                ret = sysdb_cache_auth(preq->domain,
                                       pd->user, password,
                                       pctx->rctx->cdb, false,
                                       &exp_date, &delay_until);

                pam_handle_cached_login(preq, ret, exp_date, delay_until);
                return;
            }
            break;
        case SSS_PAM_CHAUTHTOK_PRELIM:
        case SSS_PAM_CHAUTHTOK:
            DEBUG(SSSDBG_FUNC_DATA,
                  "Password change not possible while offline.\n");
            pd->pam_status = PAM_AUTHTOK_ERR;
            user_info_type = SSS_PAM_USER_INFO_OFFLINE_CHPASS;
            ret = pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
                                   (const uint8_t *) &user_info_type);
            if (ret != EOK) {
                DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
                goto done;
            }
            break;
/* TODO: we need the pam session cookie here to make sure that cached
 * authentication was successful */
        case SSS_PAM_SETCRED:
        case SSS_PAM_ACCT_MGMT:
        case SSS_PAM_OPEN_SESSION:
        case SSS_PAM_CLOSE_SESSION:
            DEBUG(SSSDBG_OP_FAILURE,
                  "Assuming offline authentication setting status for "
                      "pam call %d to PAM_SUCCESS.\n", pd->cmd);
            pd->pam_status = PAM_SUCCESS;
            break;
        default:
            DEBUG(SSSDBG_CRIT_FAILURE, "Unknown PAM call [%d].\n", pd->cmd);
            pd->pam_status = PAM_MODULE_UNKNOWN;
        }
    }

    if (pd->response_delay > 0) {
        ret = gettimeofday(&tv, NULL);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "gettimeofday failed [%d][%s].\n",
                      errno, strerror(errno));
            goto done;
        }
        tv.tv_sec += pd->response_delay;
        tv.tv_usec = 0;
        pd->response_delay = 0;

        te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
        if (te == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "Failed to add event pam_reply_delay.\n");
            goto done;
        }

        return;
    }

    /* If this was a successful login, save the lastLogin time */
    if (pd->cmd == SSS_PAM_AUTHENTICATE &&
        pd->pam_status == PAM_SUCCESS &&
        preq->domain->cache_credentials &&
        !pd->offline_auth &&
        !pd->last_auth_saved &&
        NEED_CHECK_PROVIDER(preq->domain->provider)) {
        ret = set_last_login(preq);
        if (ret != EOK) {
            goto done;
        }
        return;
    }

    ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
                         &cctx->creq->out);
    if (ret != EOK) {
        goto done;
    }

    ret = filter_responses(pctx->rctx->cdb, pd->resp_list);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "filter_responses failed, not fatal.\n");
    }

    if (pd->domain != NULL) {
        ret = pam_add_response(pd, SSS_PAM_DOMAIN_NAME, strlen(pd->domain)+1,
                               (uint8_t *) pd->domain);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
            goto done;
        }
    }

    resp_c = 0;
    resp_size = 0;
    resp = pd->resp_list;
    while(resp != NULL) {
        if (!resp->do_not_send_to_client) {
            resp_c++;
            resp_size += resp->len;
        }
        resp = resp->next;
    }

    ret = sss_packet_grow(cctx->creq->out, sizeof(int32_t) +
                                           sizeof(int32_t) +
                                           resp_c * 2* sizeof(int32_t) +
                                           resp_size);
    if (ret != EOK) {
        goto done;
    }

    sss_packet_get_body(cctx->creq->out, &body, &blen);
    DEBUG(SSSDBG_FUNC_DATA, "blen: %zu\n", blen);
    p = 0;

    memcpy(&body[p], &pd->pam_status, sizeof(int32_t));
    p += sizeof(int32_t);

    memcpy(&body[p], &resp_c, sizeof(int32_t));
    p += sizeof(int32_t);

    resp = pd->resp_list;
    while(resp != NULL) {
        if (!resp->do_not_send_to_client) {
            memcpy(&body[p], &resp->type, sizeof(int32_t));
            p += sizeof(int32_t);
            memcpy(&body[p], &resp->len, sizeof(int32_t));
            p += sizeof(int32_t);
            memcpy(&body[p], resp->data, resp->len);
            p += resp->len;
        }

        resp = resp->next;
    }

done:
    sss_cmd_done(cctx, preq);
}
コード例 #6
0
ファイル: dp_auth_util.c プロジェクト: 3van/sssd
bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error)
{
    DBusMessageIter iter;
    DBusMessageIter array_iter;
    DBusMessageIter struct_iter;
    DBusMessageIter sub_iter;
    int type;
    int len;
    const uint8_t *data;

    if (!dbus_message_iter_init(msg, &iter)) {
        DEBUG(SSSDBG_CRIT_FAILURE, "pam response has no arguments.\n");
        return false;
    }

    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
        DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
        return false;
    }
    dbus_message_iter_get_basic(&iter, &(pd->pam_status));

    if (!dbus_message_iter_next(&iter)) {
        DEBUG(SSSDBG_CRIT_FAILURE, "pam response has too few arguments.\n");
        return false;
    }

    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
        DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
        return false;
    }
    dbus_message_iter_get_basic(&iter, &(pd->account_locked));

    if (!dbus_message_iter_next(&iter)) {
        DEBUG(SSSDBG_CRIT_FAILURE, "pam response has too few arguments.\n");
        return false;
    }

    /* After this point will be an array of pam data */
    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
        DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Type was %c\n", (char)dbus_message_iter_get_arg_type(&iter));
        return false;
    }

    if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
        DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
        return false;
    }

    dbus_message_iter_recurse(&iter, &array_iter);
    while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
        /* Read in a pam data struct */
        if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
            DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
            return false;
        }

        dbus_message_iter_recurse(&array_iter,  &struct_iter);

        /* PAM data struct contains a type and a byte-array of data */

        /* Get the pam data type */
        if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_UINT32) {
            DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
            return false;
        }
        dbus_message_iter_get_basic(&struct_iter, &type);

        if (!dbus_message_iter_next(&struct_iter)) {
            DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
            return false;
        }

        /* Get the byte array */
        if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_ARRAY ||
            dbus_message_iter_get_element_type(&struct_iter) != DBUS_TYPE_BYTE) {
            DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n");
            return false;
        }

        dbus_message_iter_recurse(&struct_iter, &sub_iter);
        dbus_message_iter_get_fixed_array(&sub_iter, &data, &len);

        if (pam_add_response(pd, type, len, data) != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
            return false;
        }
        dbus_message_iter_next(&array_iter);
    }

    return true;
}