4 #include <json-c/json.h>
5 #include <security/pam_appl.h>
6 #include <security/pam_misc.h>
8 #define AFB_BINDING_VERSION 2
9 #include <afb/afb-binding.h>
11 static struct pam_conv conv = { misc_conv, NULL };
13 static char* current_device = NULL;
14 static char* current_user = NULL;
16 afb_event evt_login, evt_logout;
18 /// @brief API's verb 'login'. Try to login a user using a device
19 /// @param[in] req The request object. Should contains a json with a "device" key.
20 static void verb_login(struct afb_req req)
22 struct json_object* args = NULL;
23 struct json_object* device_object = NULL;
29 AFB_ERROR("[login] the current user must be logged out first!");
30 afb_req_fail(req, "current user must be logged out first!", NULL);
34 args = afb_req_json(req);
35 if (args == NULL || !json_object_object_get_ex(args, "device", &device_object))
37 AFB_ERROR("[login] device must be provided!");
38 afb_req_fail(req, "device must be provided!", NULL);
42 const char* device = json_object_get_string(device_object);
44 if ((r = pam_start("agl", NULL, &conv, &pamh)) != PAM_SUCCESS)
46 AFB_ERROR("PAM start failed!");
47 afb_req_fail(req, "PAM start failed!", NULL);
51 char pam_variable[4096] = "DEVICE=";
52 strcat(pam_variable, device);
54 if ((r = pam_putenv(pamh, pam_variable)) != PAM_SUCCESS)
56 AFB_ERROR("PAM putenv failed!");
57 afb_req_fail(req, "PAM putenv failed!", NULL);
62 if ((r = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
64 AFB_ERROR("PAM authenticate failed!");
65 afb_req_fail(req, "PAM authenticate failed!", NULL);
70 if ((r = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS)
72 AFB_ERROR("PAM acct_mgmt failed!");
73 afb_req_fail(req, "PAM acct_mgmt failed!", NULL);
79 pam_get_item(pamh, PAM_USER, (const void**)&pam_user);
82 AFB_ERROR("[login] No user provided by the PAM module!");
83 afb_req_fail(req, "No user provided by the PAM module!", NULL);
87 current_device = strdup(device);
88 current_user = strdup(pam_user);
90 if ((r = pam_end(pamh, r)) != PAM_SUCCESS)
92 AFB_ERROR("PAM end failed!");
93 afb_req_fail(req, "PAM end failed!", NULL);
97 AFB_INFO("[login] device: %s, user: %s", current_device, current_user);
98 json_object* result = json_object_new_object();
99 json_object_object_add(result, "device", json_object_new_string(current_device));
100 json_object_object_add(result, "user", json_object_new_string(current_user));
101 afb_req_success(req, NULL, current_device);
102 afb_event_broadcast(evt_login, result);
105 /// @brief API's verb 'lgout'. Try to logout a user using a device
106 /// @param[in] req The request object. Should contains a json with a "device" key.
107 static void verb_logout(struct afb_req req)
109 struct json_object* args = NULL;
110 struct json_object* device_object = NULL;
112 args = afb_req_json(req);
113 if (args == NULL || !json_object_object_get_ex(args, "device", &device_object))
115 AFB_INFO("[logout] device must be provided!");
116 afb_req_fail(req, "device must be provided!", NULL);
120 const char* device = json_object_get_string(device_object);
121 if (current_device && !strcmp(device, current_device))
123 free(current_device);
124 current_device = NULL;
129 AFB_INFO("[logout] device: %s", device);
130 afb_req_success(req, NULL, device);
131 afb_event_broadcast(evt_logout, NULL);
136 AFB_INFO("No user was linked to this device!");
137 afb_req_fail(req, "No user was linked to this device!", NULL);
142 AFB_INFO("The unplugged device wasn't the user key!");
143 afb_req_fail(req, "The unplugged device wasn't the user key!", NULL);
146 static void verb_getuser(struct afb_req req)
148 if (!current_device || !current_user)
150 afb_req_fail(req, "there is no logged user!", NULL);
154 json_object* result = json_object_new_object();
155 json_object_object_add(result, "user", json_object_new_string(current_user));
156 json_object_object_add(result, "device", json_object_new_string(current_device));
158 afb_req_success(req, result, NULL);
164 current_device = NULL;
165 evt_login = afb_daemon_make_event("login");
166 evt_logout = afb_daemon_make_event("logout");
168 if (afb_event_is_valid(evt_login) && afb_event_is_valid(evt_logout))
171 AFB_ERROR("Can't create events");
175 static const afb_verb_v2 _ll_auth_binding_verbs[]= {
178 .callback = verb_login,
181 .session = AFB_SESSION_NONE_V2
185 .callback = verb_logout,
188 .session = AFB_SESSION_NONE_V2
192 .callback = verb_getuser,
195 .session = AFB_SESSION_NONE_V2
200 const struct afb_binding_v2 afbBindingV2 = {
202 .specification = NULL,
203 .verbs = _ll_auth_binding_verbs,
204 .preinit = ll_auth_init,