2 Copyright (c) 2013 Eugene Crosser
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must
13 not claim that you wrote the original software. If you use this
14 software in a product, an acknowledgment in the product documentation
15 would be appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must
18 not be misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source
44 #ifdef HAVE_SECURITY_PAM_APPL_H
45 # include <security/pam_appl.h>
47 #ifdef HAVE_SECURITY_PAM_MODULES_H
48 # include <security/pam_modules.h>
50 #ifdef HAVE_SECURITY_PAM_EXT_H
51 # include <security/pam_ext.h>
56 # define PAM_EXTERN static
58 # define PAM_EXTERN extern
68 #ifndef HAVE_PAM_GET_AUTHTOK
69 static int pam_get_authtok(pam_handle_t *pamh, int item, const char **authtok,
72 struct _cfg dfl_cfg = {0};
73 struct _cfg *cfg = &dfl_cfg;
74 struct pam_conv *conv;
75 struct pam_message msg;
76 const struct pam_message *msgp;
77 struct pam_response *resp;
80 (void)pam_get_data(pamh, "pcsc_cr_cfg_struct", (const void **)&cfg);
82 if ((pam_err = pam_get_item(pamh, PAM_AUTHTOK,
83 (const void **)authtok))) {
84 if (cfg->verbose) syslog(LOG_ERR,
85 "get_item(PAM_AUTHTOK) failed: %s",
86 pam_strerror(pamh, pam_err));
88 if (*authtok) return PAM_SUCCESS;
91 if ((pam_err = pam_get_item(pamh, PAM_CONV,
92 (const void **)&conv))) {
93 if (cfg->verbose) syslog(LOG_ERR,
94 "get_item(PAM_CONV) failed: %s",
95 pam_strerror(pamh, pam_err));
98 msg.msg_style = PAM_PROMPT_ECHO_OFF;
102 pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
104 if (pam_err == PAM_SUCCESS) *authtok = resp->resp;
105 else free(resp->resp);
112 static struct _auth_chunk
113 token_key(const unsigned char *challenge, const int challengesize)
115 struct _auth_chunk ho = {0};
117 int keysize = sizeof(ho.data);
119 if ((rc = pcsc_cr(challenge, challengesize, ho.data, &keysize))) {
120 ho.err = pcsc_errstr(rc);
125 static void update_nonce(char *nonce, const int nonsize)
129 sscanf(nonce, "%d", &n);
130 snprintf(nonce, nonsize, "%d", n+1);
133 void parse_cfg(struct _cfg * const cfg, int argc, const char *argv[])
137 for (i = 0; i < argc; i++) {
138 if (cfg->verbose) syslog(LOG_DEBUG, "arg: \"%s\"", argv[i]);
139 if (strchr(argv[i],':') && strchr(argv[i],'='))
140 pcsc_option(argv[i]);
141 else if (!strcmp(argv[i], "verbose")) cfg->verbose = 1;
142 else if (!strcmp(argv[i], "noaskpass")) cfg->noaskpass = 1;
143 else if (!strcmp(argv[i], "injectauth")) cfg->injectauth = 1;
144 else if (!strncmp(argv[i], "path=", 5))
145 authfile_template(argv[i]+5);
150 pam_sm_authenticate(pam_handle_t *pamh, int flags,
151 int argc, const char *argv[])
153 struct _cfg cfg = {0};
154 const char *tokenid = NULL;
156 const char *password;
160 parse_cfg(&cfg, argc, argv);
161 (void)pam_set_data(pamh, "pcsc_cr_cfg_struct", &cfg, NULL);
163 if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) {
164 if (cfg.verbose) syslog(LOG_ERR, "get_user failed: %s",
165 pam_strerror(pamh, pam_err));
168 if (strspn(user, "0123456789") == strlen(user)) {
173 if (!cfg.noaskpass) {
174 if ((pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
175 (const char **)&password,
176 "Token password:"))) {
177 if (cfg.verbose) syslog(LOG_ERR,
178 "get_authtok failed: %s",
179 pam_strerror(pamh, pam_err));
186 ao = authfile(tokenid, user, password, update_nonce,
187 NULL, 0, NULL, 0, token_key);
189 if (cfg.verbose) syslog(LOG_INFO, "authfile: %s", ao.err);
193 pam_set_item(pamh, PAM_USER, ao.data);
194 if (cfg.injectauth && ao.payload && ao.payload[0])
195 pam_set_item(pamh, PAM_AUTHTOK, ao.payload);
201 pam_sm_setcred(pam_handle_t *pamh, int flags,
202 int argc, const char *argv[])
208 pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
209 int argc, const char *argv[])
215 pam_sm_open_session(pam_handle_t *pamh, int flags,
216 int argc, const char *argv[])
222 pam_sm_close_session(pam_handle_t *pamh, int flags,
223 int argc, const char *argv[])
229 pam_sm_chauthtok(pam_handle_t *pamh, int flags,
230 int argc, const char *argv[])
232 return PAM_SERVICE_ERR;
235 #ifdef PAM_MODULE_ENTRY
236 PAM_MODULE_ENTRY("pam_pcsc_cr");
240 struct pam_module _pam_pcsc_cr_modstruct = {
246 pam_sm_close_session,