6
Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
7
Copyright (C) Sumit Bose <sbose@redhat.com> 2009
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 3 of the License, or
12
(at your option) any later version.
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include <security/pam_modules.h>
25
#include "util/util.h"
27
#include "util/nss_sha512crypt.h"
28
#include "providers/data_provider.h"
29
#include "responder/pam/pamsrv.h"
31
static int authtok2str(const void *mem_ctx,
32
uint8_t *src, const int src_size,
37
if ((src == NULL && src_size != 0) ||
38
(src != NULL && *src != '\0' && src_size == 0)) {
42
dest = talloc_size(mem_ctx, src_size + 1);
47
memcpy(dest, src, src_size);
54
static void pam_cache_auth_return(struct pam_auth_req *preq, int error)
56
preq->pd->pam_status = error;
60
static void pam_cache_auth_callback(void *pvt, int ldb_status,
61
struct ldb_result *res)
63
struct pam_auth_req *preq;
68
char *password = NULL;
70
uint64_t lastLogin = 0;
72
preq = talloc_get_type(pvt, struct pam_auth_req);
75
pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
77
if (ldb_status != LDB_SUCCESS) {
78
DEBUG(4, ("User info retrieval failed! (%d [%s])\n",
79
ldb_status, sysdb_error_to_errno(ldb_status)));
85
if (res->count == 0) {
86
DEBUG(4, ("User [%s@%s] not found.\n",
87
pd->user, preq->domain->name));
88
ret = PAM_USER_UNKNOWN;
92
if (res->count != 1) {
93
DEBUG(4, ("Too many results for user [%s@%s].\n",
94
pd->user, preq->domain->name));
99
/* Check offline_auth_cache_timeout */
100
lastLogin = ldb_msg_find_attr_as_uint64(res->msgs[0],
101
SYSDB_LAST_ONLINE_AUTH,
103
if (pctx->cred_expiration &&
104
lastLogin + (pctx->cred_expiration * 86400) < time(NULL)) {
105
DEBUG(4, ("Cached user entry is too old."));
106
ret = PAM_AUTHINFO_UNAVAIL;
110
/* TODO: verify user account (failed logins, disabled, expired ...) */
112
ret = authtok2str(preq, pd->authtok, pd->authtok_size, &password);
114
DEBUG(4, ("Invalid auth token.\n"));
119
userhash = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_CACHEDPWD, NULL);
120
if (userhash == NULL || *userhash == '\0') {
121
DEBUG(4, ("Cached credentials not available.\n"));
122
ret = PAM_AUTHINFO_UNAVAIL;
126
ret = s3crypt_sha512(preq, password, userhash, &comphash);
128
DEBUG(4, ("Failed to create password hash.\n"));
129
ret = PAM_SYSTEM_ERR;
133
if (strcmp(userhash, comphash) == 0) {
134
/* TODO: probable good point for audit logging */
135
DEBUG(4, ("Hashes do match!\n"));
140
DEBUG(4, ("Authentication failed.\n"));
144
if (password) for (i = 0; password[i]; i++) password[i] = 0;
145
pam_cache_auth_return(preq, ret);
148
int pam_cache_auth(struct pam_auth_req *preq)
150
struct sysdb_ctx *sysdb;
153
static const char *attrs[] = {SYSDB_NAME,
157
SYSDB_LAST_ONLINE_AUTH,
158
"lastCachedPasswordChange",
160
"failedLoginAttempts",
164
ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
165
preq->domain, &sysdb);
167
DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
170
ret = sysdb_get_user_attr(preq, sysdb,
171
preq->domain, preq->pd->user, attrs,
172
pam_cache_auth_callback, preq);
175
DEBUG(2, ("sysdb_get_user_attr failed.\n"));