b25ba5c8ab08000f74c9160e8edf9ef9311f241e
[apps/agl-service-data-persistence.git] / pam_agl / pam_agl_nfc.c
1 #include <fcntl.h>
2 #include <stdarg.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <uuid/uuid.h>
9 #include <json-c/json.h>
10
11 #define PAM_SM_AUTH
12 #define PAM_SM_ACCOUNT
13 #define PAM_SM_SESSION
14 #define PAM_SM_PASSWORD
15 #include <security/pam_modules.h>
16 #include <security/pam_appl.h>
17
18 #include <security/pam_client.h>
19 #include <security/pam_ext.h>
20 #include <security/pam_filter.h>
21 #include <security/pam_misc.h>
22 #include <security/pam_modutil.h>
23
24 #define DATABASE_FILE "/etc/agl/keys.json"
25
26 int authenticate(pam_handle_t* pamh, const char* uid)
27 {
28         struct json_object* database;
29         struct json_object* nfc;
30         struct json_object* key;
31
32         database = json_object_from_file(DATABASE_FILE);
33         if (!database)
34         {
35                 printf("[PAM DEBUG] Failed to parse the database\n");
36                 return PAM_SERVICE_ERR;
37         }
38         
39         if (json_object_object_get_ex(database, "nfc", &nfc))
40         {       
41                 if (json_object_object_get_ex(nfc, uid, &key))
42                 {
43                         printf("[PAM] Key found!\n");
44                         printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uid);
45                         pam_set_item(pamh, PAM_USER, uid);
46                                 
47                         const char* pam_authtok;
48                         if (pam_get_item(pamh, PAM_AUTHTOK, (const void**)&pam_authtok) == PAM_SUCCESS && !pam_authtok)
49                                 pam_set_item(pamh, PAM_AUTHTOK, uid);
50                         
51                         json_object_put(database);
52                         return PAM_SUCCESS;
53                 }
54         }
55         
56         printf("[PAM] Key not found!\n");
57         if (database) json_object_put(database);
58         return PAM_AUTH_ERR;
59 }
60
61 int check_device(pam_handle_t* pamh, const char* device)
62 {
63         char* idkey;
64         int ret;
65         
66         ret = read_device(device, &idkey);
67         if (ret != PAM_SUCCESS) return ret;
68         
69         printf("[PAM DEBUG] Data read:\n%s\n", idkey);
70         
71         json_object* idkey_json = json_tokener_parse(idkey);
72         if (!idkey_json)
73         {
74                 free(idkey);
75                 printf("[PAM DEBUG] Failed to parse json data!\n");
76                 return PAM_SERVICE_ERR;
77         }
78
79         json_object* uuid_json;
80         if(!json_object_object_get_ex(idkey_json, "uuid", &uuid_json))
81         {
82                 free(idkey);
83                 printf("[PAM DEBUG] The json does not contains a valid uuid\n");
84                 return PAM_SERVICE_ERR;
85         }
86
87         const char* uuid = json_object_get_string(uuid_json);
88         printf("[PAM DEBUG] uuid: %s\n", uuid);
89         
90         ret = authenticate(pamh, uuid);
91         free(idkey);
92         json_object_put(idkey_json);
93         return ret;
94 }
95
96 void log_pam(const char* fname, int flags, int argc, const char** argv, const char* device)
97 {
98         printf("[PAM DEBUG] ---------- %s ----------\n", fname);
99         printf("[PAM DEBUG] flags: %d\n", flags);
100         for(int i = 0; i < argc; ++i)
101         {
102                 printf("[PAM DEBUG] argv[%d]: %s\n", i, argv[i]);
103         }
104         printf("[PAM DEBUG] device: %s\n", device);
105         printf("[PAM DEBUG] ----------------------------------------\n");
106 }
107
108 /*!
109         @brief The pam_sm_authenticate function is the service module's implementation
110         of the pam_authenticate(3) interface.
111         This function performs the task of authenticating the user.
112
113         @param[in] pamh Unknown.
114         @param[in] flags PAM_SILENT and/or PAM_DISALLOW_NULL_AUTHTOK.
115         @return PAM_SUCCESS if ok.
116 */
117 PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv)
118 {
119         const char* uid = pam_getenv(pamh, "UID");
120         log_pam("pam_sm_authenticate", flags, argc, argv, uid);
121         return authenticate(pamh, uid);
122 }
123
124 PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv)
125 {
126         log_pam("pam_sm_setcred", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
127         return PAM_SUCCESS;
128 }
129
130 PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv)
131 {
132         log_pam("pam_sm_acct_mgmt", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
133         return PAM_SUCCESS;
134 }
135
136 PAM_EXTERN int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
137 {
138         log_pam("pam_sm_open_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
139         return PAM_SUCCESS;
140 }
141
142 PAM_EXTERN int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
143 {
144         log_pam("pam_sm_close_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
145         return PAM_SUCCESS;
146 }
147
148 PAM_EXTERN int pam_sm_chauthtok(pam_handle_t* pamh, int flags, int argc, const char** argv)
149 {
150         log_pam("pam_sm_chauthtok", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
151         return PAM_SUCCESS;
152 }