typecast for snprintf
[pam_pcsc_cr.git] / pam_pcsc_cr.c
1 /*
2 Copyright (c) 2013 Eugene Crosser
3
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.
7
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:
11
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.
16
17     2. Altered source versions must be plainly marked as such, and must
18     not be misrepresented as being the original software.
19
20     3. This notice may not be removed or altered from any source
21     distribution.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <stdarg.h>
33 #include <syslog.h>
34 #include "authobj.h"
35 #include "authfile.h"
36 #include "pcsc_cr.h"
37
38 #ifndef PIC
39 # define PAM_STATIC
40 #endif
41
42 #define PAM_SM_AUTH
43
44 #ifdef HAVE_SECURITY_PAM_APPL_H
45 # include <security/pam_appl.h>
46 #endif
47 #ifdef HAVE_SECURITY_PAM_MODULES_H
48 # include <security/pam_modules.h>
49 #endif
50
51 #ifndef PAM_EXTERN
52 # ifdef PAM_STATIC
53 #  define PAM_EXTERN static
54 # else
55 #  define PAM_EXTERN extern
56 # endif
57 #endif
58
59 static struct _auth_chunk
60 token_key(const unsigned char *challenge, const int challengesize)
61 {
62         struct _auth_chunk ho = {0};
63         long rc;
64         int keysize = sizeof(ho.data);
65
66         if ((rc = pcsc_cr(challenge, challengesize, ho.data, &keysize))) {
67                 ho.err = pcsc_errstr(rc);
68         }
69         return ho;
70 }
71
72 static void update_nonce(char *nonce, const int nonsize)
73 {
74         int n = 0;
75
76         sscanf(nonce, "%d", &n);
77         snprintf(nonce, nonsize, "%d", n+1);
78 }
79
80 struct _cfg {
81         int noaskpass;
82         int verbose;
83         int injectauth;
84 };
85
86 void parse_cfg(struct _cfg * const cfg, int argc, const char *argv[])
87 {
88         int i;
89
90         for (i = 0; i < argc; i++) {
91                 if (cfg->verbose) syslog(LOG_DEBUG, "arg: \"%s\"", argv[i]);
92                 if (strchr(argv[i],':') && strchr(argv[i],'='))
93                         pcsc_option(argv[i]);
94                 else if (!strcmp(argv[i], "verbose")) cfg->verbose = 1;
95                 else if (!strcmp(argv[i], "noaskpass")) cfg->noaskpass = 1;
96                 else if (!strcmp(argv[i], "injectauth")) cfg->injectauth = 1;
97                 else if (!strncmp(argv[i], "path=", 5))
98                                         authfile_template(argv[i]+5);
99         }
100 }
101
102 PAM_EXTERN int
103 pam_sm_authenticate(pam_handle_t *pamh, int flags,
104         int argc, const char *argv[])
105 {
106         struct _cfg cfg = {0};
107         const char *tokenid = NULL;
108         const char *user;
109         const char *password;
110         struct _auth_obj ao;
111         int pam_err;
112
113         parse_cfg(&cfg, argc, argv);
114
115         if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) {
116                 if (cfg.verbose) syslog(LOG_ERR, "get_user failed: %s",
117                                         pam_strerror(pamh, pam_err));
118                 return pam_err;
119         }
120         if (strspn(user, "0123456789") == strlen(user)) {
121                 tokenid = user;
122                 user = NULL;
123         }
124
125         if (!cfg.noaskpass) {
126 #ifdef _OPENPAM
127                 pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
128                                         (const char **)&password, NULL);
129 #else
130                 struct pam_conv *conv;
131                 struct pam_message msg;
132                 const struct pam_message *msgp;
133                 struct pam_response *resp;
134
135                 if ((pam_err = pam_get_item(pamh, PAM_CONV,
136                                         (const void **)&conv))) {
137                         if (cfg.verbose) syslog(LOG_ERR,
138                                         "get_item failed: %s",
139                                         pam_strerror(pamh, pam_err));
140                         return pam_err;
141                 }
142                 msg.msg_style = PAM_PROMPT_ECHO_OFF;
143                 msg.msg = "Token password:";
144                 msgp = &msg;
145                 resp = NULL;
146                 pam_err =  (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
147                 if (resp != NULL) {
148                         if (pam_err == PAM_SUCCESS) password = resp->resp;
149                         else free(resp->resp);
150                         free(resp);
151                 }
152 #endif
153                 if (pam_err) return pam_err;
154         } else {
155                 password = "";
156         }
157
158         ao = authfile(tokenid, user, password, update_nonce,
159                         NULL, 0, NULL, 0, token_key);
160         if (ao.err) {
161                 if (cfg.verbose) syslog(LOG_INFO, "authfile: %s", ao.err);
162                 return PAM_AUTH_ERR;
163         } else {
164                 if (!user)
165                         pam_set_item(pamh, PAM_USER, ao.data);
166                 if (cfg.injectauth && ao.payload && ao.payload[0])
167                         pam_set_item(pamh, PAM_AUTHTOK, ao.payload);
168                 return PAM_SUCCESS;
169         }
170 }
171
172 PAM_EXTERN int
173 pam_sm_setcred(pam_handle_t *pamh, int flags,
174         int argc, const char *argv[])
175 {
176         return PAM_SUCCESS;
177 }
178
179 PAM_EXTERN int
180 pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
181         int argc, const char *argv[])
182 {
183         return PAM_SUCCESS;
184 }
185
186 PAM_EXTERN int
187 pam_sm_open_session(pam_handle_t *pamh, int flags,
188         int argc, const char *argv[])
189 {
190         return PAM_SUCCESS;
191 }
192
193 PAM_EXTERN int
194 pam_sm_close_session(pam_handle_t *pamh, int flags,
195         int argc, const char *argv[])
196 {
197         return PAM_SUCCESS;
198 }
199
200 PAM_EXTERN int
201 pam_sm_chauthtok(pam_handle_t *pamh, int flags,
202         int argc, const char *argv[])
203 {
204         return PAM_SERVICE_ERR;
205 }
206
207 #ifdef PAM_MODULE_ENTRY
208 PAM_MODULE_ENTRY("pam_unix");
209 #endif
210
211 #ifdef PAM_STATIC
212 struct pam_module _pam_pcsc_cr_modstruct = {
213         "pam_pcsc_cr",
214         pam_sm_authenticate,
215         pam_sm_setcred,
216         pam_sm_acct_mgmt,
217         pam_sm_open_session,
218         pam_sm_close_session,
219         pam_sm_chauthtok
220 };
221 #endif