#include "mdm.h" #include #include #include MwWidget root = NULL; MwWidget window, sesscombo, usercombo, passentry, reason; typedef struct session { char* key; session_environment_t* value; } session_t; session_t* sessions = NULL; char* name_line = NULL; char* try_exec_line = NULL; char* exec_line = NULL; char* desktop_names_line = NULL; int session_count = 0; int mde_count = -1; static void add_user(const char* name, void* user) { MwComboBoxAdd(user, -1, name); } static int dumper(void* user, const char* section, const char* name, const char* value) { if(strcmp(section, "Desktop Entry") != 0) return 1; if(strcmp(name, "Name") == 0) { name_line = MDEStringDuplicate(value); } else if(strcmp(name, "TryExec") == 0) { try_exec_line = MDEStringDuplicate(value); } else if(strcmp(name, "Exec") == 0) { exec_line = MDEStringDuplicate(value); } else if(strcmp(name, "DesktopNames") == 0) { desktop_names_line = MDEStringDuplicate(value); } return 1; } static void add_session(session_type_t session_type, const char* path, int dir, int symlink, void* user) { int m = 1; session_environment_t* value = malloc(sizeof(session_environment_t)); name_line = NULL; exec_line = NULL; try_exec_line = NULL; desktop_names_line = NULL; if(dir || symlink) return; ini_parse(path, dumper, user); if(name_line != NULL && (exec_line != NULL || try_exec_line != NULL)) { int i; for(i = 0; i < shlen(sessions); i++) { if(strcmp(sessions[i].key, name_line) == 0) break; } if(i == shlen(sessions)) { MwComboBoxAdd(user, -1, name_line); if(strcmp(name_line, "MDE") == 0) { mde_count = session_count; } session_count++; value->run = exec_line; value->try_run = try_exec_line; value->session_type = session_type; value->desktop_names = desktop_names_line; shput(sessions, name_line, value); m = 0; } } if(name_line != NULL) free(name_line); if(m && desktop_names_line != NULL) free(desktop_names_line); if(m && try_exec_line != NULL) free(try_exec_line); if(m && exec_line != NULL) free(exec_line); } static void add_session_x(const char* path, int dir, int symlink, void* user) { add_session(MDM_SESSION_TYPE_X, path, dir, symlink, user); } static void add_session_wayland(const char* path, int dir, int symlink, void* user) { add_session(MDM_SESSION_TYPE_WAYLAND, path, dir, symlink, user); } static int conversation(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata) { int i; *resp = malloc(num_msg * sizeof(struct pam_response)); for(i = 0; i < num_msg; i++) { if(msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) { const char* txt = MwGetText(passentry, MwNtext); if(txt == NULL) txt = ""; resp[i]->resp_retcode = PAM_SUCCESS; resp[i]->resp = MDEStringDuplicate(txt); } else { return PAM_CONV_ERR; } } return PAM_SUCCESS; } static void try_login(MwWidget handle, void* user, void* client) { const char* username; const char* place; struct pam_conv conv; pam_handle_t* pam; int err; int err2; int ret; char err_str[255]; int print_error = 0; int i, n; username = MwComboBoxGet(usercombo, MwGetInteger(usercombo, MwNvalue)); conv.conv = conversation; conv.appdata_ptr = NULL; err = 1; (void)handle; (void)user; (void)client; ret = pam_start("mdm", username, &conv, &pam); if(ret != PAM_SUCCESS) { place = "Error calling pam_start"; goto cleanup; } ret = pam_authenticate(pam, 0); if(ret != PAM_SUCCESS) { place = "Error calling pam_authenticate"; goto cleanup; } ret = pam_acct_mgmt(pam, 0); if(ret != PAM_SUCCESS) { place = "Error calling pam_acct_mgmt"; goto cleanup; } cleanup: // if pam_end fails but we have another error, we care more about the error at hand // then whether pam successfully ended. err2 = pam_end(pam, 0); if(err && ret != PAM_SUCCESS) { MwSetText(passentry, MwNtext, ""); snprintf(err_str, 255, "%s: %s", place, pam_strerror(pam, err)); print_error = 1; } else if(err2) { MwSetText(passentry, MwNtext, ""); snprintf(err_str, 255, "Error calling pam_end: %s", pam_strerror(pam, err2)); print_error = 1; } if(print_error) { n = 0; for(i = 0; err_str[i] != '\0' && i <= 255; i++ && n++) { if(err_str[i] == ' ' && n >= 40) { err_str[i] = '\n'; n = 0; } } MwSetText(reason, MwNtext, "Login failed"); } else { printf("Logging in as %s\n", username); struct passwd* pwd = getpwnam(username); const char* session = MwComboBoxGet(sesscombo, MwGetInteger(sesscombo, MwNvalue)); uid = pwd->pw_uid; gid = pwd->pw_gid; env = shget(sessions, session); MwDestroyWidget(root); } } void login_window(void) { MwWidget pic, userlabel, passlabel, mainsep, sesslabel, fieldsep, shutdown, reboot, ok; MwLLPixmap p; void* out; int i; pthread_mutex_lock(&xmutex); MwLibraryInit(); root = MwVaCreateWidget(NULL, "root", NULL, 0, 0, 0, 0, COMMON_LOOK, NULL); window = MwVaCreateWidget(MwWindowClass, "login", root, (x_width() - 366) / 2, (x_height() - 183) / 2, 366, 183, MwNtitle, "login", NULL); p = config_picture == NULL ? NULL : MwLoadImage(window, config_picture); pic = MwVaCreateWidget(MwImageClass, "image", window, 10, 10, 80, 137, MwNhasBorder, 1, NULL); userlabel = MwVaCreateWidget(MwLabelClass, "userlabel", window, 95, 10, MwTextWidth(window, NULL, "User:"), 16, MwNtext, "User:", NULL); usercombo = MwCreateWidget(MwComboBoxClass, "usercombo", window, 95, 10 + 16 + 5, 265, 18); passlabel = MwVaCreateWidget(MwLabelClass, "passlabel", window, 95, 10 + 16 + 5 + 18 + 5, MwTextWidth(window, NULL, "Password:"), 16, MwNtext, "Password:", NULL); passentry = MwVaCreateWidget(MwEntryClass, "passentry", window, 95, 10 + 16 + 5 + 18 + 5 + 16 + 5, 265, 18, MwNhideInput, 1, NULL); mainsep = MwVaCreateWidget(MwSeparatorClass, "mainsep", window, 95, 10 + 16 + 5 + 18 + 5 + 16 + 5 + 18, 265, 10, MwNorientation, MwHORIZONTAL, NULL); sesslabel = MwVaCreateWidget(MwLabelClass, "sesslabel", window, 95, 10 + 16 + 5 + 18 + 5 + 16 + 5 + 18 + 10, MwTextWidth(window, NULL, "Session Type:"), 16, MwNtext, "Session Type:", NULL); sesscombo = MwCreateWidget(MwComboBoxClass, "sesscombo", window, 95, 10 + 16 + 5 + 18 + 5 + 16 + 5 + 18 + 10 + 16 + 5, 265, 18); fieldsep = MwVaCreateWidget(MwSeparatorClass, "fieldsep", window, 10, 10 + 137, 351, 10, MwNorientation, MwHORIZONTAL, NULL); shutdown = MwVaCreateWidget(MwButtonClass, "shutdown", window, 10, 10 + 137 + 10, 80, 18, MwNtext, "Shut Down", NULL); reboot = MwVaCreateWidget(MwButtonClass, "reboot", window, 10 + 80 + 5, 10 + 137 + 10, 70, 18, MwNtext, "Reboot", NULL); ok = MwVaCreateWidget(MwButtonClass, "ok", window, 366 - 10 - 60, 10 + 137 + 10, 60, 18, MwNtext, "OK", NULL); reason = MwCreateWidget(MwLabelClass, "ok", window, 10 + 80 + 5 + 70 + 5, 10 + 137 + 10, 366 - 10 - 80 - 5 - 70 - 5 - 60 - 10 - 5, 18); if(p != NULL) MwVaApply(pic, MwNpixmap, p, NULL); MwAddUserHandler(ok, MwNactivateHandler, try_login, NULL); MwAddUserHandler(passentry, MwNactivateHandler, try_login, NULL); MDEUsersList(add_user, usercombo); for(i = 0; i < shlen(sessions); i++) { if(sessions[i].value->desktop_names != NULL) free(sessions[i].value->desktop_names); free(sessions[i].value); } shfree(sessions); sh_new_strdup(sessions); shdefault(sessions, NULL); mde_count = -1; session_count = 0; MDEDirectoryScan(DATAROOTDIR "/xsessions", add_session_x, sesscombo); MDEDirectoryScan("/usr/share/xsessions", add_session_x, sesscombo); MDEDirectoryScan(DATAROOTDIR "/wayland-sessions", add_session_wayland, sesscombo); MDEDirectoryScan("/usr/share/wayland-sessions", add_session_wayland, sesscombo); if(mde_count != -1) { MwVaApply(sesscombo, MwNvalue, mde_count, NULL); } pthread_mutex_unlock(&xmutex); while(1) { int s = 0; pthread_mutex_lock(&xmutex); while(MwPending(root)) { if((s = MwStep(root)) != 0) break; } pthread_mutex_unlock(&xmutex); if(s != 0) break; MwTimeSleep(30); } pthread_join(xthread, &out); }