3e246e4d13b95e1e00fc60a0c27daeff8096e1a3
[apps/agl-service-data-persistence.git] / pam_agl / pam_agl.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 #define BLOCK_SIZE 4096
19 typedef struct header_
20 {
21         char mn[4];
22         size_t size;
23 } header;
24
25 int is_valid_mn(const char* v)
26 {
27         return v && v[0] == 'I' && v[1] == 'D' && v[2] == 'K' && v[3] == 'Y';
28 }
29
30 void pam_putenv_ex(pam_handle_t* pamh, const char* name, const char* value)
31 {
32         char result[4096];
33         strcpy(result, name);
34
35         int offset = strlen(name);
36         result[offset] = '=';
37
38         strcpy(result + offset + 1, value);
39
40         pam_putenv(pamh, result);
41 }
42
43 int check_device(pam_handle_t* pamh, const char* device)
44 {
45         printf("[PAM DEBUG]: check_device %s...\n", device);
46         int fd = open(device, O_RDONLY);
47         if (fd == -1)
48         {
49                 printf("[PAM DEBUG]: Failed to open the device %s!\n", device);
50                 return PAM_SERVICE_ERR;
51         }
52
53         header h;
54         ssize_t sz = read(fd, &h, sizeof(header));
55         if (sz != sizeof(header) || !is_valid_mn(h.mn) || h.size < 1) { close(fd); printf("[PAM DEBUG]: bad header!\n"); return PAM_SERVICE_ERR; }
56         printf("[PAM DEBUG]: data size=%d\n", h.size);
57
58         char* idkey = (char*)malloc(h.size + 1);
59         if (!idkey) { close(fd); printf("[PAM DEBUG] Bad alloc!\n"); return PAM_SERVICE_ERR; }
60
61         memset(idkey, 0, h.size + 1);
62         size_t count = read(fd, idkey, h.size);
63         close(fd);
64
65         if (count != h.size) { free(idkey); printf("[PAM DEBUG] Bad data read!\n"); return PAM_SERVICE_ERR; }
66         printf("[PAM DEBUG] Data read:\n%s\n", idkey);
67
68         json_object* idkey_json = json_tokener_parse(idkey);
69         if (!idkey_json) { free(idkey); printf("[PAM DEBUG] Failed to parse json data!\n"); return PAM_SERVICE_ERR; }
70
71         json_object* uuid_json;
72         if(!json_object_object_get_ex(idkey_json, "uuid", &uuid_json)) { free(idkey); printf("[PAM DEBUG]: The json does not contains a valid uuid\n"); return PAM_SERVICE_ERR; }
73
74         const char* uuid = json_object_get_string(uuid_json);
75         printf("[PAM DEBUG] uuid: %s\n", uuid);
76
77         // TODO: Check if the uuid is accepted
78         const char* const ids[] = {
79                 "4f29e9ea-600a-11e7-8331-c70192ecfa55",
80                 "13126524-6256-11e7-be33-3f4e4481a8c9",
81                 NULL
82         };
83
84         int i = 0;
85         while(ids[i])
86         {
87                 if (!strcmp(ids[i], uuid))
88                 {
89                         printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uuid);
90                         pam_set_item(pamh, PAM_USER, uuid);
91                         
92                         const char* pam_authtok;
93                         if (pam_get_item(pamh, PAM_AUTHTOK, (const void**)&pam_authtok) == PAM_SUCCESS && !pam_authtok)
94                                 pam_set_item(pamh, PAM_AUTHTOK, uuid);
95
96                         return PAM_SUCCESS;
97                 }
98                 ++i;
99         }
100         
101         return PAM_AUTH_ERR;
102 }
103
104 void log_pam(const char* fname, int flags, int argc, const char** argv, const char* device)
105 {
106         printf("[PAM DEBUG]: ---------- %s ----------\n", fname);
107         printf("[PAM DEBUG]: flags: %d\n", flags);
108         for(int i = 0; i < argc; ++i)
109         {
110                 printf("[PAM DEBUG]: argv[%d]: %s\n", i, argv[i]);
111         }
112         printf("[PAM DEBUG]: device: %s\n", device);
113         printf("[PAM DEBUG]: ----------------------------------------\n");
114 }
115
116 /*!
117         @brief The pam_sm_authenticate function is the service module's implementation
118         of the pam_authenticate(3) interface.
119         This function performs the task of authenticating the user.
120
121         @param[in] pamh Unknown.
122         @param[in] flags PAM_SILENT and/or PAM_DISALLOW_NULL_AUTHTOK.
123         @return PAM_SUCCESS if ok.
124 */
125 PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv)
126 {
127         const char* device = pam_getenv(pamh, "DEVICE");
128         log_pam("pam_sm_authenticate", flags, argc, argv, device);
129         return check_device(pamh, device);
130 }
131
132 PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv)
133 {
134         log_pam("pam_sm_setcred", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
135         return PAM_SUCCESS;
136 }
137
138 PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv)
139 {
140         log_pam("pam_sm_acct_mgmt", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
141         return PAM_SUCCESS;
142 }
143
144 PAM_EXTERN int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
145 {
146         log_pam("pam_sm_open_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
147         return PAM_SUCCESS;
148 }
149
150 PAM_EXTERN int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
151 {
152         log_pam("pam_sm_close_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
153         return PAM_SUCCESS;
154 }
155
156 PAM_EXTERN int pam_sm_chauthtok(pam_handle_t* pamh, int flags, int argc, const char** argv)
157 {
158         log_pam("pam_sm_chauthtok", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
159         return PAM_SUCCESS;
160 }