initial PAM module
[pam_pcsc_cr.git] / pam_pcsc_cr.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <stdarg.h>
10 #include <syslog.h>
11 #include "authobj.h"
12 #include "authfile.h"
13 #include "pcsc_cr.h"
14
15 #ifndef PIC
16 # define PAM_STATIC
17 #endif
18
19 #define PAM_SM_AUTH
20
21 #ifdef HAVE_SECURITY_PAM_APPL_H
22 # include <security/pam_appl.h>
23 #endif
24 #ifdef HAVE_SECURITY_PAM_MODULES_H
25 # include <security/pam_modules.h>
26 #endif
27
28 #ifndef PAM_EXTERN
29 # ifdef PAM_STATIC
30 #  define PAM_EXTERN static
31 # else
32 #  define PAM_EXTERN extern
33 # endif
34 #endif
35
36 static struct _auth_chunk
37 token_key(const unsigned char *challenge, const int challengesize)
38 {
39         struct _auth_chunk ho = {0};
40         long rc;
41         int keysize = sizeof(ho.data);
42
43         if ((rc = pcsc_cr(challenge, challengesize, ho.data, &keysize))) {
44                 ho.err = pcsc_errstr(rc);
45         }
46         return ho;
47 }
48
49 static void update_nonce(char *nonce, const int nonsize)
50 {
51         int n = 0;
52
53         sscanf(nonce, "%d", &n);
54         snprintf(nonce, nonsize, "%d", n+1);
55 }
56
57 struct _cfg {
58         int verbose;
59 };
60
61 void parse_cfg(struct _cfg * const cfg, int argc, const char *argv[])
62 {
63         int i;
64
65         for (i = 0; i < argc; i++) {
66                 if (strchr(argv[i],':') && strchr(argv[i],'='))
67                         pcsc_option(argv[i]);
68                 else if (!strcmp(argv[i], "verbose")) cfg->verbose = 1;
69         }
70 }
71
72 PAM_EXTERN int
73 pam_sm_authenticate(pam_handle_t *pamh, int flags,
74         int argc, const char *argv[])
75 {
76         struct _cfg cfg;
77         const char *tokenid = NULL;
78         const char *user;
79         const char *password;
80         struct _auth_obj ao;
81         int pam_err;
82
83         parse_cfg(&cfg, argc, argv);
84
85         if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) {
86                 if (cfg.verbose) syslog(LOG_ERR, "get_user failed: %s",
87                                         pam_strerror(pamh, pam_err));
88                 return (pam_err);
89         }
90         if (strspn(user, "0123456789") == strlen(user)) {
91                 tokenid = user;
92                 user = NULL;
93         }
94
95         if (flags & PAM_DISALLOW_NULL_AUTHTOK) {
96                 if ((pam_err = pam_get_item(pamh, PAM_AUTHTOK,
97                                         (const void **)&password))) {
98                         if (cfg.verbose) syslog(LOG_ERR,
99                                         "get_authtok failed: %s",
100                                         pam_strerror(pamh, pam_err));
101                         return (pam_err);
102                 }
103         } else {
104                 password = "";
105         }
106
107         ao = authfile(tokenid, user, password, update_nonce,
108                         NULL, 0, NULL, 0, token_key);
109         if (ao.err) {
110                 if (cfg.verbose) syslog(LOG_INFO, "authfile: %s", ao.err);
111                 return PAM_AUTH_ERR;
112         } else {
113                 if (!user)
114                         pam_set_item(pamh, PAM_USER, ao.data);
115                 if (ao.payload && ao.payload[0])
116                         pam_set_item(pamh, PAM_AUTHTOK, ao.payload);
117                 return PAM_SUCCESS;
118         }
119 }
120
121 PAM_EXTERN int
122 pam_sm_setcred(pam_handle_t *pamh, int flags,
123         int argc, const char *argv[])
124 {
125         return PAM_SUCCESS;
126 }
127
128 PAM_EXTERN int
129 pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
130         int argc, const char *argv[])
131 {
132         return PAM_SUCCESS;
133 }
134
135 PAM_EXTERN int
136 pam_sm_open_session(pam_handle_t *pamh, int flags,
137         int argc, const char *argv[])
138 {
139         return PAM_SUCCESS;
140 }
141
142 PAM_EXTERN int
143 pam_sm_close_session(pam_handle_t *pamh, int flags,
144         int argc, const char *argv[])
145 {
146         return PAM_SUCCESS;
147 }
148
149 PAM_EXTERN int
150 pam_sm_chauthtok(pam_handle_t *pamh, int flags,
151         int argc, const char *argv[])
152 {
153         return PAM_SERVICE_ERR;
154 }
155
156 #ifdef PAM_MODULE_ENTRY
157 PAM_MODULE_ENTRY("pam_unix");
158 #endif
159
160 #ifdef PAM_STATIC
161 struct pam_module _pam_pcsc_cr_modstruct = {
162         "pam_pcsc_cr",
163         pam_sm_authenticate,
164         pam_sm_setcred,
165         pam_sm_acct_mgmt,
166         pam_sm_open_session,
167         pam_sm_close_session,
168         pam_sm_chauthtok
169 };
170 #endif